首页
社区
课程
招聘
[原创]看雪 2016 CTF 第二十六 Solution
发表于: 2016-12-24 12:13 5244

[原创]看雪 2016 CTF 第二十六 Solution

HHHso 活跃值
22
2016-12-24 12:13
5244

在主函数体00401BB0 _main中
程序先解密出局部存储的加密注入目标进程镜像名称"Broiler.exe"
其作为下属启动的调试线程Hi_debug_handler_sub_401040的线程参数
.text:00401C20 push    eax             ; lpThreadId
.text:00401C21 push    0               ; dwCreationFlags
.text:00401C23 push    ecx             ; lpParameter
.text:00401C24 push    offset Hi_debug_handler_sub_401040 ; lpStartAddress
.text:00401C29 push    0               ; dwStackSize
.text:00401C2B push    0               ; lpThreadAttributes
.text:00401C2D call    ds:CreateThread

调试线程会启动目标进程"Broiler.exe"并捕捉调试事件,主要处理是注入线程的两次int 3中断事件
下属是处理两次int 3事件的调用栈
Hi_debug_handler_sub_401040
  0040104A call Hi_startDebug_P1ProcessName_sub_401D40
    00401E5B call Hi_CaseDebugEventCode1_sub_401F20
      00401F87 call    Hi_debugEvent_80000003_sub_401FA0

在Hi_debugEvent_80000003_sub_401FA0中为两次处理int3的分支
.text:00401FFE cmp eax, 2
.text:00402001 jnz loc_4020D2 //-------响应第一次int3事件
.text:00402007 xor eax, eax   //-------响应第二次int3事件

第一次int3事件响应通过WriteProcessMemory将中断EIP处的两字节修正为 0x90,0x2A
004020E3 call ds:WriteProcessMemory
实际将原 "int 3"、"add al,cl" 两指令修正为 "nop"、"sub al,cl"

第二次int3事件响应会读取注入线程(算法2,alg2)处理后的注册码key2,
再与局部存储的key比对,完全匹配则显示成功
.text:0040209E call ds:ReadProcessMemory //读取经过注入线程alg2算法变换后的keyInfo
.text:004020A4 xor ecx, ecx
.text:004020A6 xor eax, eax
.text:004020A8 loc_4020A8:                             ;
.text:004020A8 mov dl, [esp+eax+40h+Buffer_key2] //key2 after alg1 and alg2
.text:004020AC cmp dl, [esp+eax+40h+var_30_tgtKey]
.text:004020B0 jz short loc_4020B3 //-var_30_tgtKey数组为局部变量存储的目标比对key
.text:004020B2 inc ecx  //----------------------ecx统计不匹配个数
.text:004020B3 loc_4020B3:                             
.text:004020B3 inc eax
.text:004020B4 cmp eax, 15h
.text:004020B7 jl short loc_4020A8
.text:004020B9 cmp ecx, ebx
.text:004020BB jnz short loc_4020D2
.text:004020BD push ebx                             ; uType
.text:004020BE push offset aJ_0                     ; "成功了"
.text:004020C3 push ebx                             ; lpText
.text:004020C4 push ebx                             ; hWnd
.text:004020C5 call ds:MessageBoxA  //--------------显示成功信息

在主函数体00401BB0 _main 中,接着是读取用户输入的注册码key,
然后经过算法1函数Hi_alg1_sar2xorIxor41h_sub_401060处理得到key1,
处理后传递给后续注入函数,
注入函数Hi_inject_alg2_thread_sub_4010D0会在捕捉Broiler.exe进程的目标线程
然后注入算法2-alg2的chip代码片段执行算法2对key做第二步处理
.text:00401C79 call    _scanf
.text:00401C7E lea     ecx, [esp+30h+var_18_key] //-------key
.text:00401C82 push    ecx
.text:00401C83 call    Hi_alg1_sar2xorIxor41h_sub_401060
.text:00401C88 lea     edx, [esp+34h+var_18_key] //-------key1 after alg1
.text:00401C8C push    edx
.text:00401C8D call    Hi_inject_alg2_thread_sub_4010D0
.text:00401C92 push    offset aPause   ; "pause"
.text:00401C97 call    _system

注入的chip代码片段如下,
其中 770000 存放输入的key,也作为chip代码算法处理后的keyInfo输出地
007800D1 和 007800D2两处的指令已经直接手工修正
算法alg2看起来有点绕,这里我们不需要从算法原理上做逆向攻击,
因为(alg2)其对key的各个字符的变换是独立的(alg1不是)。
所以我们可以直接用alg2的变换码表来实现逆向解密。

如何获取码表?
1.调试注入的chip代码
a. OD 启动 CrackMe.exe主进程,在入口处停下,
  将Hi_debug_handler_sub_401040函数体修改为无用函数,即,
  在函数首地址401040处汇编为 xor eax,eax 和 ret 4
b. OD 启动 Broiler.exe被注入进程,直接跑起
c. CrackMe.exe断点设置于00401B84 call ds:ResumeThread
   跑起"a.",任意输入回车断下。
   下述全局变量存储了key和注入的chip代码的首地址
   Hi_va200h_for_key_dword_40CA6C
   Hi_va1000h_chip_dword_40CA68
d.在Broiler.exe进程的Hi_va1000h_chip_dword_40CA68地址下F2断点,
  (需要查看进程内存布局M控件刷新下),然后对"c."断下的进程直接单步
  或F9跑起,这时Broiler.exe进程就会断下在下述注入的chip代码片段处

00780000   68 00007700      PUSH 770000
00780005   C745 FC 00000000 MOV DWORD PTR SS:[EBP-4],0
0078000C   8965 FC          MOV DWORD PTR SS:[EBP-4],ESP
0078000F   8B45 FC          MOV EAX,DWORD PTR SS:[EBP-4]
00780012   B3 2A            MOV BL,2A
00780014   B2 3F            MOV DL,3F
00780016   C645 C4 8C       MOV BYTE PTR SS:[EBP-3C],8C
0078001A   8B08             MOV ECX,DWORD PTR DS:[EAX]
0078001C   B0 B6            MOV AL,0B6
0078001E   C645 C5 4C       MOV BYTE PTR SS:[EBP-3B],4C
00780022   C645 C6 96       MOV BYTE PTR SS:[EBP-3A],96
00780026   C645 C7 5B       MOV BYTE PTR SS:[EBP-39],5B
0078002A   885D C8          MOV BYTE PTR SS:[EBP-38],BL
0078002D   8855 C9          MOV BYTE PTR SS:[EBP-37],DL
00780030   8845 CA          MOV BYTE PTR SS:[EBP-36],AL
00780033   C645 CB 5B       MOV BYTE PTR SS:[EBP-35],5B
00780037   885D CC          MOV BYTE PTR SS:[EBP-34],BL
0078003A   C645 CD 11       MOV BYTE PTR SS:[EBP-33],11
0078003E   C645 CE B1       MOV BYTE PTR SS:[EBP-32],0B1
00780042   C645 CF 15       MOV BYTE PTR SS:[EBP-31],15
00780046   C645 D0 AC       MOV BYTE PTR SS:[EBP-30],0AC
0078004A   C645 D1 C3       MOV BYTE PTR SS:[EBP-2F],0C3
0078004E   C645 D2 53       MOV BYTE PTR SS:[EBP-2E],53
00780052   8845 D3          MOV BYTE PTR SS:[EBP-2D],AL
00780055   885D D4          MOV BYTE PTR SS:[EBP-2C],BL
00780058   8855 D5          MOV BYTE PTR SS:[EBP-2B],DL
0078005B   C645 D6 B2       MOV BYTE PTR SS:[EBP-2A],0B2
0078005F   C645 D7 FC       MOV BYTE PTR SS:[EBP-29],0FC
00780063   C645 D8 69       MOV BYTE PTR SS:[EBP-28],69
00780067   C645 D9 10       MOV BYTE PTR SS:[EBP-27],10
0078006B   C645 DA BF       MOV BYTE PTR SS:[EBP-26],0BF
0078006F   C645 DB FD       MOV BYTE PTR SS:[EBP-25],0FD
00780073   8845 DC          MOV BYTE PTR SS:[EBP-24],AL
00780076   C645 DD 5B       MOV BYTE PTR SS:[EBP-23],5B
0078007A   8855 DE          MOV BYTE PTR SS:[EBP-22],DL
0078007D   894D E4          MOV DWORD PTR SS:[EBP-1C],ECX
00780080   C745 E0 15000000 MOV DWORD PTR SS:[EBP-20],15
00780087   8D55 C4          LEA EDX,DWORD PTR SS:[EBP-3C]
0078008A   8D45 C4          LEA EAX,DWORD PTR SS:[EBP-3C]
0078008D   C745 F4 00000000 MOV DWORD PTR SS:[EBP-C],0
00780094   8955 EC          MOV DWORD PTR SS:[EBP-14],EDX
00780097   8945 F0          MOV DWORD PTR SS:[EBP-10],EAX
0078009A   8B55 F0          MOV EDX,DWORD PTR SS:[EBP-10]
0078009D   8B45 EC          MOV EAX,DWORD PTR SS:[EBP-14]
007800A0   33FF             XOR EDI,EDI
007800A2   8955 FC          MOV DWORD PTR SS:[EBP-4],EDX
007800A5   897D E8          MOV DWORD PTR SS:[EBP-18],EDI
007800A8   8945 F8          MOV DWORD PTR SS:[EBP-8],EAX
007800AB   8B75 FC          MOV ESI,DWORD PTR SS:[EBP-4]
007800AE   33D2             XOR EDX,EDX
007800B0   8B45 F8          MOV EAX,DWORD PTR SS:[EBP-8]
007800B3   8A19             MOV BL,BYTE PTR DS:[ECX]
007800B5   8A0410           MOV AL,BYTE PTR DS:[EAX+EDX]
007800B8   3AD8             CMP BL,AL
007800BA   75 22            JNZ SHORT 007800DE
007800BC   8D0C17           LEA ECX,DWORD PTR DS:[EDI+EDX]
007800BF   8B7D F4          MOV EDI,DWORD PTR SS:[EBP-C]
007800C2   8D3C4F           LEA EDI,DWORD PTR DS:[EDI+ECX*2]
007800C5   03CF             ADD ECX,EDI
007800C7   0FBEFB           MOVSX EDI,BL
007800CA   0FBE4C0D C4      MOVSX ECX,BYTE PTR SS:[EBP+ECX-3C]
007800CF   33CF             XOR ECX,EDI//-------下述相应第一次int3事件后修正
007800D1   90               NOP        //-------int 3     修正为 nop
007800D2   2AC1             SUB AL,CL  //-------add al,cl 修正为 sub al,cl
007800D4   8B4D E4          MOV ECX,DWORD PTR SS:[EBP-1C]
007800D7   F62E             IMUL BYTE PTR DS:[ESI]
007800D9   8B7D E8          MOV EDI,DWORD PTR SS:[EBP-18]
007800DC   8801             MOV BYTE PTR DS:[ECX],AL
007800DE   42               INC EDX
007800DF   83C6 09          ADD ESI,9
007800E2   83FA 04          CMP EDX,4
007800E5  ^7C C9            JL SHORT 007800B0
007800E7   8B5D FC          MOV EBX,DWORD PTR SS:[EBP-4]
007800EA   8B55 F8          MOV EDX,DWORD PTR SS:[EBP-8]
007800ED   83C7 03          ADD EDI,3
007800F0   43               INC EBX
007800F1   83C2 03          ADD EDX,3
007800F4   83FF 06          CMP EDI,6
007800F7   895D FC          MOV DWORD PTR SS:[EBP-4],EBX
007800FA   897D E8          MOV DWORD PTR SS:[EBP-18],EDI
007800FD   8955 F8          MOV DWORD PTR SS:[EBP-8],EDX
00780100  ^7C A9            JL SHORT 007800AB
00780102   8B45 F4          MOV EAX,DWORD PTR SS:[EBP-C]
00780105   8B7D F0          MOV EDI,DWORD PTR SS:[EBP-10]
00780108   8B75 EC          MOV ESI,DWORD PTR SS:[EBP-14]
0078010B   40               INC EAX
0078010C   83C7 03          ADD EDI,3
0078010F   83C6 09          ADD ESI,9
00780112   83F8 03          CMP EAX,3
00780115   8945 F4          MOV DWORD PTR SS:[EBP-C],EAX
00780118   897D F0          MOV DWORD PTR SS:[EBP-10],EDI
0078011B   8975 EC          MOV DWORD PTR SS:[EBP-14],ESI
0078011E  ^0F8C 76FFFFFF    JL 0078009A
00780124   8B45 E0          MOV EAX,DWORD PTR SS:[EBP-20]
00780127   41               INC ECX
00780128   48               DEC EAX
00780129   894D E4          MOV DWORD PTR SS:[EBP-1C],ECX
0078012C   8945 E0          MOV DWORD PTR SS:[EBP-20],EAX
0078012F  ^0F85 52FFFFFF    JNZ 00780087
00780135   90               NOP
00780136   90               NOP
00780137   90               NOP
00780138   CC               INT3 //第二次触发int3事件,调试进程会检验keyInfo

2.产生算法alg2变换码表,
a.执行到上述chip代码片段 00780087 处,修正ebp-20,key长度为0x100,
  当然,也可以在00780080执行前将该指令的立即数修改为0x100,
00780080   C745 E0 15000000 MOV DWORD PTR SS:[EBP-20],15
00780087   8D55 C4          LEA EDX,DWORD PTR SS:[EBP-3C]
b.修改注入的key,00770000缓冲区做为输入的key1(也作为输出的key2缓冲区)
  修改为下述[0x00,0xFF]字符,这里由于用的是OD,修改起来有点麻烦
如果是IDA(WINDBG),直接执行下述两行IDAPython代码即可
for i in xrange(0,0x100):
  PatchByte(0x770000+i,i)
没办法,一开始选择了OD,自己挖的坑,哭着也得跳,只能用笨办法补救了。
以下是鼠标手和键盘手展示时间,
OD修改 00770000  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F,不用16秒吧
Binary复制上述一行,
将后续15行全部粘贴为00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F,不用48秒吧
对00770010行,"1"和"->"交替按键速度应该不用8秒吧,另外8秒歇息下逼下一招;
对00770020行,"2"和"->"交替按键速度应该不用8秒吧,另外8秒歇息下逼下一招;
...
对007700F0行,"F"和"->"交替按键速度应该不用8秒吧,另外8秒逼下一招;没有下一招了!
c.经过a,b的修改,和第一个int3附近的修正,直接断在上述chip代码片段尾部也是第二个int3处,
直跑断下,就会得到下述key对应的keyInfo码表。我们用keyInfo码表解密最终的比对key2,
就可得到alg1加密后的key1

00770000:[IN]key1
00770000  00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
00770010  10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
00770020  20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
00770030  30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
00770040  40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
00770050  50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
00770060  60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
00770070  70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
00770080  80 81 82 83 84 85 86 87 88 89 8A 8B 8C 8D 8E 8F
00770090  90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D 9E 9F
007700A0  A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF
007700B0  B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF
007700C0  C0 C1 C2 C3 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
007700D0  D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
007700E0  E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
007700F0  F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB FC FD FE FF
007700F0  F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB 86 F9 FE FF

00770000:[OUT]key2Table for key2
$ ==>    >00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
$+10     >00 86 12 13 14 70 16 17 18 19 1A 1B 1C 1D 1E 1F
$+20     >20 21 22 23 24 25 26 27 28 29 64 2B 2C 2D 2E 2F
$+30     >30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 28
$+40     >40 41 42 43 44 45 46 47 48 49 4A 4B 85 4D 4E 4F
$+50     >50 51 52 A6 54 55 56 57 58 59 5A EF 5C 5D 5E 5F
$+60     >60 61 62 63 64 65 66 67 68 04 6A 6B 6C 6D 6E 6F
$+70     >70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
$+80     >80 81 82 83 84 85 86 87 88 89 8A 8B 90 8D 88 8F
$+90     >90 91 92 93 94 95 0C 97 98 99 9A 9B 9C 9D 9E 9F
$+A0     >A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB 00 AD AE AF
$+B0     >B0 C8 F4 B3 B4 B5 74 B7 B8 B9 BA BB BC BD BE 9E
$+C0     >C0 C1 C2 89 C4 C5 C6 C7 C8 C9 CA CB CC CD CE CF
$+D0     >D0 D1 D2 D3 D4 D5 D6 D7 D8 D9 DA DB DC DD DE DF
$+E0     >E0 E1 E2 E3 E4 E5 E6 E7 E8 E9 EA EB EC ED EE EF
$+F0     >F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 FA FB 86 F9 FE FF

在上面的Hi_debugEvent_80000003_sub_401FA0函数中,追踪比对的key2从局部数组变量中提取为
key2 = [0xEF, 0x86, 0x85, 0x0C, 0xD2, 0x89, 0x64, 0xA6, 0x9E, 0xC8, 0xCC, 0x70, 0x00, 0x90, 0x09, 0xF4, 0x28, 0x6E, 0x5A, 0x04, 0xF9]
对于key2[0]=0xEF,通过查表,我们可以得到对应的key1[0]为 0x5B 或 0xEF
我们通过后面的anti_alg1类枚举key1对应的输入key,sar2xorIxor41h为alg1算法的python实现
由于alg1算法加密时前后关联的,所以只能从左到右一位一位来
anti_alg1(ktp = [],i=0,alg1v = 0x5b)函数中,ktp为已经确定的key前面的字符,i为要确定的第i个字符(0起),
alg1v为key[i]变换后的key1[i]的值
求key[0]
anti_alg1([],0,0x5B)
anti_alg1([],0,0xEF)
得到
68 5B h
69 5B i
6A 5B j
6B 5B k
94 5B
95 5B
96 5B
97 5B
即key[0]可以是"h","i","j","k"
对于key2[1]查表可得,key1[1]取值为 0x11,0x86,0xFC
求key[1]
>>> anti_alg1(['j'],1,0x11)
>>> anti_alg1(['j'],1,0x86)
>>> anti_alg1(['j'],1,0xFC)
>>> anti_alg1(['h'],1,0xFC)
>>> anti_alg1(['h'],1,0x86)
>>> anti_alg1(['h'],1,0x11)
>>> anti_alg1(['i'],1,0x11)
>>> anti_alg1(['i'],1,0x86)
>>> anti_alg1(['i'],1,0xFC)
>>> anti_alg1(['k'],1,0xFC)
00 5B
即这时候只能是key[0]="k",key[1]="\0"(有点不合常理,这个该整么输入?不急,继续往后看看)
同理key2[2]=0x85,对于key1[2]取值为 0x4C,0x85
>>> anti_alg1(['k','\0'],2,0x85)
>>> anti_alg1(['k','\0'],2,0x4C)
00 4C
得到key[2] = '\0'
再来求得下述依然是key[3]='\0'
>>> alg1(['k','\0','\0'],3,0x96)
00 96

这时候我就没再往后尝试了,直接在提交框提交"k",好吧,通过了,就这么简单
实际的key="k",等效于key="k\0\0\0\0\0\0\0\0\0\0\0\0\0\0"

#-------
kt = create_stirng_buffer("\0"*0x15)

def anti_alg1(ktp = [],i=0,alg1v = 0x5b):
  kt=create_string_buffer('\0'*0x15)
  for j in xrange(0,ktp.__len__()):
    kt[j] = ktp[j]
  for ch in xrange(0,0x100):
    kt[i] = chr(ch)
    sar2xorIxor41h(kt)
    if ord(kt[i])==alg1v:
      print "{:02X} {:02X} {}".format(ch,ord(kt[0]),chr(ch))

def sar2xorIxor41h(kt):
  esi = c_ulong(0)
  eax = c_ulong(0)
  cl = c_ubyte(0)
  ecx = c_ulong(0)
  ebx = c_ulong(0)
  esi.value = c_byte(ord(kt[0])).value
  edx = 0
  while edx < 0x15:
    cl.value = c_byte(ord(kt[0])).value
    eax.value = esi.value
    eax.value = c_long(eax.value).value >> 8
    cl.value = c_byte(cl.value).value >> 2
    eax.value = (eax.value ^ cl.value) & 0xFF
    kt[edx]=chr(eax.value)
    eax.value += esi.value
    ecx.value = eax.value * 9
    ecx.value = (ecx.value * 2) + eax.value
    ecx.value = ecx.value * 3
    ecx.value = ecx.value << 4
    ecx.value += eax.value
    eax.value = esi.value
    eax.value = c_long(eax.value).value>>2
    ebx.value = ecx.value * 3
    ecx.value = eax.value
    ecx.value = ecx.value << 5
    ecx.value = ecx.value - eax.value
    ecx.value = ecx.value * 3
    ecx.value = eax.value + (ecx.value * 4)
    ecx.value = ecx.value * 3
    eax.value = eax.value + (ecx.value * 2)
    eax.value = eax.value << 2
    esi.value = eax.value + (ebx.value * 2)
    kt[edx] = chr(ord(kt[edx]) ^ 0x41)
    edx += 1

#-------


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回