首页
社区
课程
招聘
[原创]看雪 2016 CTF 第八题 Solution
发表于: 2016-11-16 20:42 2997

[原创]看雪 2016 CTF 第八题 Solution

HHHso 活跃值
22
2016-11-16 20:42
2997
1.第一阶段IDA做静态分析,定位主业务逻辑函数体,其完成的注册码信息加载初始化、用户输入注册码初步处理并进入最终校验。
2.第二阶段Windbg动态调试,验证部分代码性质,结合静态分析得到注册码。

1.静态分析。
(1.1)由下面中文提示信息溯源到主要业务逻辑函数体 sub_140001910,
(该信息在IDA Striing 中为乱码,直接点击跟进)
.rdata:0000000140022008 aVSI db '注册码:',0   

(1.2)在下面的 sub_140001910 函数体内
a. Hi_Init_wwA5x5_sub_140001400 加载注册文件,并初始化注册信息二维数组 Hi_wwKeyInfoArray5x5_140025CC0[5][5]。
b. Hi_console_in_fmt_sub_1400012B0 格式化 "%dA%s" 请求用户输入的注册码 KeyMAstr。
c. Hi_get_Mr_for_KeyM_sub_140001300 从用户输入的 KeyMAstr 信息中的 M 获取相应的平方根 Mr。
d. Hi_CheckKeyAstr_with_Mr_sub_1400014B0 检测 KeyMAstr 的 Astr 和 Mr。

  
//sub_140001910 函数体主要业务逻辑
.text:0000000140001910 ; =============== S U B R O U T I N E =======================================
.text:0000000140001910
.text:0000000140001910
.text:0000000140001910 sub_140001910   proc near               ; CODE XREF: sub_140001ADC+11Fp
.text:0000000140001910                                         ; DATA XREF: .pdata:0000000140026084o
.text:0000000140001910
.text:0000000140001910 var_428_KeyM    = dword ptr -428h
.text:0000000140001910 var_418_KeyAstr = byte ptr -418h
.text:0000000140001910 var_18          = qword ptr -18h
.text:0000000140001910
.text:0000000140001910                 sub     rsp, 448h
.text:0000000140001917                 mov     rax, cs:__security_cookie
.text:000000014000191E                 xor     rax, rsp
.text:0000000140001921                 mov     [rsp+448h+var_18], rax
.text:0000000140001929                 xor     edx, edx
.text:000000014000192B                 lea     rcx, [rsp+448h+var_418_KeyAstr]
.text:0000000140001930                 mov     r8d, 400h
.text:0000000140001936                 call    Hi_memset_sub_140002C10 ;
.text:0000000140001936                                         ; memset(ecx,edx,cbszie:r8)
.text:000000014000193B                 lea     rcx, unk_140021FA0 ;
.text:000000014000193B ;   请将序列号文件存放在程序运行目录下,并命名为names.in 格式参见帖子
.text:000000014000193B ; By 无名侠
.text:0000000140001942                 call    Hi_Console_out_sub_140001200
.text:0000000140001947                 call    Hi_Init_wwA5x5_sub_140001400
.text:000000014000194C                 test    al, al
.text:000000014000194E                 jz      short loc_140001995
.text:0000000140001950                 lea     rcx, aVSI       ; "注册码:"
.text:0000000140001957                 call    Hi_Console_out_sub_140001200
.text:000000014000195C                 lea     r8, [rsp+448h+var_418_KeyAstr]
.text:0000000140001961                 lea     rdx, [rsp+448h+var_428_KeyM]
.text:0000000140001966                 lea     rcx, aDaS       ; "%dA%s"
.text:000000014000196D                 call    Hi_console_in_fmt_sub_1400012B0
.text:0000000140001972                 call    Hi_end0_sub_14000A634
.text:0000000140001977                 mov     ecx, [rsp+448h+var_428_KeyM]
.text:000000014000197B                 call    Hi_get_Mr_for_KeyM_sub_140001300  
.text:0000000140001980                 test    eax, eax
.text:0000000140001982                 jnz     short loc_1400019AF
.text:0000000140001984                 lea     rcx, unk_140022018 ;
.text:0000000140001984                                         ; 注册码有误!
.text:000000014000198B                 call    Hi_Console_out_sub_140001200
.text:0000000140001990                 call    Hi_end0_sub_14000A634
.text:0000000140001995
.text:0000000140001995 loc_140001995:                          ; CODE XREF: sub_140001910+3Ej
.text:0000000140001995                 xor     eax, eax
.text:0000000140001997                 mov     rcx, [rsp+448h+var_18]
.text:000000014000199F                 xor     rcx, rsp
.text:00000001400019A2                 call    sub_1400019D0
.text:00000001400019A7                 add     rsp, 448h
.text:00000001400019AE                 retn
.text:00000001400019AF
.text:00000001400019AF
.text:00000001400019AF loc_1400019AF:                          ; CODE XREF: sub_140001910+72j
.text:00000001400019AF                 lea     rdx, [rsp+448h+var_418_KeyAstr]
.text:00000001400019B4                 mov     ecx, eax
.text:00000001400019B6                 call    Hi_CheckKeyAstr_with_Mr_sub_1400014B0
                       ; ---------------------------------------------------------------------------
                       
                       
(1.2.a)Hi_Init_wwA5x5_sub_140001400 中 Hi_wwKeyInfoArray5x5_140025CC0[5][5] 数据加载初始化
.text:0000000140001426                 lea     rbx, Hi_wwA5x5_unk_140025CC0
.text:000000014000142D                 mov     [rsp+28h+arg_8], rbp
.text:0000000140001432                 mov     ebp, 5
.text:0000000140001437                 mov     [rsp+28h+arg_10], rdi
.text:000000014000143C                 nop     dword ptr [rax+00h]
.text:0000000140001440
.text:0000000140001440 loc_140001440:                          ;-----------------------外循环5
.text:0000000140001440                 mov     edi, 5
.text:0000000140001445                 db      66h, 66h
.text:0000000140001445                 nop     word ptr [rax+rax+00000000h]
.text:0000000140001450
.text:0000000140001450 loc_140001450:                          ; -----------------内循环5
.text:0000000140001450                 mov     r8, rbx
.text:0000000140001453                 lea     rdx, aD         ; "%d"
.text:000000014000145A                 mov     rcx, rsi
.text:000000014000145D                 call    Hi_file_scanf_fmt_sub_140001260
.text:0000000140001462                 add     rbx, 4
.text:0000000140001466                 sub     rdi, 1
.text:000000014000146A                 jnz     short loc_140001450
.text:000000014000146C                 sub     rbp, 1
.text:0000000140001470                 jnz     short loc_140001440
.text:0000000140001472                 mov     rcx, rsi
.text:0000000140001475                 call    Hi_close_file_sub_140003AC8

(1.2.b) 注册码结构 "[M]A[Astr]"

(1.2.c) 求M的平方根的算法类似于下述python代码
可见其是通过枚举的方式求M的平方根的,
所以一旦M的平方根不是自然数,将进入"死"循环。

def getMr(M):
  # for 987654321 or 874 return -1
  MDecMode = pow(10,len(str(M)))
  Mr = 1
  while ((Mr*Mr) % MDecMode) != M:
    Mr = Mr + 1
  return Mr
  
(1.2.d)Hi_CheckKeyAstr_with_Mr_sub_1400014B0 中对 KeyMAstr 中 Astr 的使用逻辑如下
//其取值范围只能是["1","2","3","4"]组成的集合,
//其用于携带序号的乘积与注册矩阵进行异或运行,并对用于选中注册信息的二维矩阵中的元素
//从(2,2)开始,"1"、"3"分别是行、列减1,"2"、"4"使之加1
// 其中个5,7等边界常量 由 sub_140001380 函数的不同输入决定, 其对于相同的输入,输出常量固定。
/*

dword_140025CBC=1;dword_140025C44=0;ecx=2 经 sub_140001380 得到 dword_140025D24 = 2 //(mfun(2,2).4 + 3)
dword_140025CBC=2;dword_140025C44=0;ecx=2 经 sub_140001380 得到 dword_140025D24 = 4
dword_140025CBC=2;dword_140025C44=0;ecx=3 经 sub_140001380 得到 dword_140025D24 = 2
*/

rsi = 2
rdi = rsi = 2
r14d.row = esi = 2
r8 = rdx = AstrPtr
r12d = esi.col - 1 = 1
rbp = rsi * 5 = 10
r13d = rsi + 1 = 3
r9d = 0
while(True){
  wwA5x5 ^= ((*AstrPtr)*r9d)
  switch(*AstrPtr){
    case "1":
      r12d should < 7 //(mfun(2,2).4 + 3)
      rdi < 5
      r14d.row--,r13d--,r12d--,rbp--5,break;
    case "2":
      r13d should < 7 //(mfun(2,2).4 + 3)
      rdi < 5
      r14d.row++,r13d++,r12d++,rbp++5,break;
    case "3":
      r14d.row shoudl < 7 //(mfun(2,2).4 + 3)
      esi.col < 6
      esi--,rdi--,break;
    case "4":
      r14d.row should < 7 //(mfun(2,2).4 + 3)
      esi.col < 4
      esi++,rdi++,break;
    default:
      "注册码格式错误"
  }
  r9d++
  AstrPtr++
  if r9d >= kslen:
    break
}
  

1.2.d.1 经过(1.2.d)上述运行得到 r14d.row=2,esi.col=2
结合 dword_140025CBC=2;dword_140025C44=0;ecx=3 经 sub_140001380 得到 dword_140025D24 = 2 常量
下述代码的比较关心为 2*Mr + Hi_wwKeyInfoArray5x5_140025CC0[r14d.row,esi.col] == Mr*3,
化简为 Hi_wwKeyInfoArray5x5_140025CC0[r14d.row.2,esi.col.2] = Mr
1.2.d.2 即对于注册码"[M]A[Astr]",对于任意满足边界条件的Astr(如1234、12341等),
可以直接构建虚假注册码9A1234、9A12341等(不一定是9,A前只要是平方数即可)输入
然后在 关键点 00000001400018A7 断下
通过dump  (Hi_wwKeyInfoArray5x5_140025CC0+r14d*5*4+esi*4) 定位到M的平方根值 Mr,从而得到 M = Mr*Mr

.text:00000001400018A7                 movsxd  rax, esi
.text:00000001400018AA                 movsxd  rdx, r14d
.text:00000001400018AD                 lea     rcx, [rax+rdx*4]
.text:00000001400018B1                 add     rdx, rcx
.text:00000001400018B4                 lea     rax, Hi_wwKeyInfoArray5x5_140025CC0
.text:00000001400018BB                 mov     ecx, cs:Hi_stepInc_2_0_2_dword_140025D24 // dword_140025D24 = 2
.text:00000001400018C1                 imul    ecx, edi   //---------------------edi = Mr, the root of M in KeyMAstr
.text:00000001400018C4                 add     ecx, [rax+rdx*4]
.text:00000001400018C7                 lea     eax, [rdi+rdi*2]
.text:00000001400018CA                 cmp     ecx, eax
.text:00000001400018CC                 lea     rcx, aZUVSJ     ; "恭喜你注册成功!\n"
.text:00000001400018D3                 jz      short loc_1400018DC
.text:00000001400018D5                 lea     rcx, unk_140021F90 ;
.text:00000001400018D5                                         ; 注册码不正确
  
  
动态调试
(2.1)上Windbg,若注册文件错误,可将CrackMe用的注册文件放在Windbg同目录下。
Executable search path is:
ModLoad: 00000001`3fd90000 00000001`3fdbb000   image00000001`3fd90000
...
ntdll!CsrSetPriorityClass+0x40:
00000000`771c1220 cc              int     3

(2.2)在(1.2.d.2)中的关键点 00000001400018A7 下断bp(如下需根据实际基地址调整),然后跑起来g
0:000> bp 13fd318a7h
0:000> bl
0 e 00000001`3fd318a7     0001 (0001)  0:**** image00000001_3fd30000+0x18a7
0:000> g

(2.3)输入 9A12345 就会在相应位置断下
Breakpoint 0 hit
image00000001_3fd30000+0x18a7:
00000001`3fd318a7 4863c6          movsxd  rax,esi
0:000> u rip  //------------------------------------------会rip处代码反汇编
image00000001_3fd30000+0x18a7:
00000001`3fd318a7 4863c6          movsxd  rax,esi
00000001`3fd318aa 4963d6          movsxd  rdx,r14d
00000001`3fd318ad 488d0c90        lea     rcx,[rax+rdx*4]
00000001`3fd318b1 4803d1          add     rdx,rcx
00000001`3fd318b4 488d0505440200  lea     rax,[image00000001_3fd30000+0x25cc0 (00000001`3fd55cc0)]
00000001`3fd318bb 8b0d63440200    mov     ecx,dword ptr [image00000001_3fd30000+0x25d24 (00000001`3fd55d24)]
00000001`3fd318c1 0fafcf          imul    ecx,edi
00000001`3fd318c4 030c90          add     ecx,dword ptr [rax+rdx*4]
0:000> r  //------------------------------------------查看寄存器状态,其中 r14=row=1, rsi=col=2
rax=0000000000000002 rbx=0000000000000002 rcx=0000000000000003
rdx=0000000000000000 rsi=0000000000000002 rdi=0000000000000003
rip=000000013fd318a7 rsp=00000000001ff750 rbp=0000000000000005
r8=000000000000000c  r9=0000000000000000 r10=000000013fd55cc0
r11=000000013fd55c40 r12=0000000000000000 r13=0000000000000002
r14=0000000000000001 r15=0000000000000005
iopl=0         nv up ei pl nz na pe nc
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202
image00000001_3fd30000+0x18a7:
00000001`3fd318a7 4863c6          movsxd  rax,esi
0:000> d (image00000001_3fd30000+0x25cc0+r14d*5*4+esi*4) //------------dump 显示目标元素(1,2)的数据,
00000001`3fd55cdc  bd 00 00 00 be 01 00 00-df 01 00 00 db 01 00 00  ................
00000001`3fd55cec  f6 00 00 00 04 00 00 00-f9 01 00 00 e7 01 00 00  ................
0:000> ?bd             //---------------------------------------------其值为0xbd,及Mr = 0xbd
Evaluate expression: 189 = 00000000`000000bd
0:000> ?(bd*bd)       //----------------------------------------------所以 M = Mr*Mr = 0xbd*0xbd >> 35721
Evaluate expression: 35721 = 00000000`00008b89

(2.4)
即输入 9A12345得到其中一个有效注册码 35721A12341
又如输入9A1234断下提取得到有效注册码 44100A1234
0:000>  d (13f815cc0h+r14d*5*4+esi*4)
00000001`3f815cf0  d2 00 00 00 0c 01 00 00-12 01 00 00 17 01 00 00  ................
0:000> ?d2
Evaluate expression: 210 = 00000000`000000d2
0:000> ?(d2*d2)
Evaluate expression: 44100 = 00000000`0000ac44

只有Astr致使(2,2)的坐标不移除5*5矩阵等边界条件,就可以Dump出相应的平方根Mr确定相应的注册码。

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

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