首页
社区
课程
招聘
[原创]看雪 2017 CTF 第一题 JzJnzJmp
发表于: 2017-6-1 22:33 2826

[原创]看雪 2017 CTF 第一题 JzJnzJmp

HHHso 活跃值
22
2017-6-1 22:33
2826

主要消除反编译干扰,在边界与有限集合中求二元一次方程的解。

0x01

随机输出key,按注册"Register"得到错误提示"error !"

0x02

上IDA,查看字符信息SubView|String,溯源"error !"字符交叉索引点,定位注册业务逻辑

(1)"SubView|String"

.data:00408040 00000008 C error !

(2)溯源"error !"字符

.data:00408030 WindowName      db 'PEDIY CTF 2017',0   ; DATA XREF: WinMain(x,x,x,x)

.data:00408040 Text            db 'error !',0          ; DATA XREF: sub_4011F4:

.data:00408048 Caption         db 'CrackMe 2017 CTF v2',0 ; DATA XREF: sub_4011F4

.data:0040805C aRegistrationSu db 'Registration successful !',0 ; DATA XREF: 

.data:00408078 aCrackme2017Ctf db 'CrackMe 2017 CTF',0 ; DATA XREF: sub_4011F4

(3)"error !"字符交叉引用定位注册代码逻辑

.text:004012BC push    0

.text:004012BE push    offset aCrackme2017Ctf ; "CrackMe 2017 CTF"

.text:004012C3 fnstsw  ax

.text:004012C5 sahf

.text:004012C6 jnz     short loc_4012D6

.text:004012C8 push    offset aRegistrationSu ; "Registration successful !"

.text:004012CD jmp     short loc_4012DB

.text:004012CF loc_4012CF:                            

.text:004012CF push    0               ; uType

.text:004012D1 push    offset Caption  ; "CrackMe 2017 CTF v2"

.text:004012D6 loc_4012D6:                             ; 

.text:004012D6 push    offset Text     ; "error !"

.text:004012DB loc_4012DB:                             ; 

.text:004012DB push    hWnd            ; hWnd

.text:004012E1 call    ds:MessageBoxA

.text:004012E7 leave

.text:004012E8 retn

0x03

清除反编译干扰代码重建判断逻辑业务函数

反汇编干扰的模式只用一种(两处)jz RealAddr\jnz RealAddr\call(0xE8) xxx\RealAddr的方式

两处干扰分别从(1.1)\(2.1)变为(1.2)\(2.2)实际控制流,通过(3)(4)(5)(6)清除干扰重建函数体逻辑

(1.1)

.text:0040125E jz      short near ptr loc_401262+1

.text:00401260 jnz     short near ptr loc_401262+1

.text:00401262 loc_401262:

.text:00401262 call    near ptr unk_48CACD

(1.2)

.text:0040125E jz      short loc_401263

.text:00401260 jnz     short loc_401263

.text:00401262 db 0E8h ; 

.text:00401263 loc_401263:

.text:00401263 mov     ax, 8

.text:00401267 xor     ax, 7

(2.1)

.text:004012A6 jz      short near ptr loc_4012AA+1

.text:004012A8 jnz     short near ptr loc_4012AA+1

.text:004012AA loc_4012AA:

.text:004012AA call    near ptr unk_48CB15

(2.2)

.text:004012A6 jz      short loc_4012AB

.text:004012A8 jnz     short loc_4012AB

.text:004012AA db 0E8h ; 

.text:004012AB loc_4012AB:    

.text:004012AB mov     ax, 8

.text:004012AF xor     ax, 7

(3)IDAPython清除[0x40125E,0x401263)区间反编译干扰冗余代码

for ea in (0x40125E,0x401263):

  PatchByte(ea,0x90)

(4)同理清除[0x4012A6,0x4012AB)区间反编译干扰冗余代码

(5)在代码块[0x40125E,0x401263)与[0x4012A6,0x4012AB)起始地址

   0x40125E和0x4012A6处快捷键"C"重建"nop"(0x90)指令

(6)在函数首地址0x4011F4处右键”Create Function“重建函数得到Hi_CheckKey_sub_4011F4

0x05

key校验函数Hi_CheckKey_sub_4011F4逻辑

(1)

.text:004011F4 push    ebp

.text:004011F5 mov     ebp, esp

.text:004011F7 sub     esp, 1Ch

.text:004011FA lea     eax, [ebp+loc_key]

.text:004011FD push    15h             ; cchMax

.text:004011FF push    eax             ; lpString

.text:00401200 push    3E9h            ; nIDDlgItem

.text:00401205 push    Hi_hDlg         ; hDlg

.text:0040120B call    ds:GetDlgItemTextA

.text:00401211 push    1F4h            ; dwMilliseconds

.text:00401216 call    ds:Sleep

.text:0040121C lea     eax, [ebp+loc_key]

.text:0040121F push    eax             ; char *

.text:00401220 call    _strlen

.text:00401225 cmp     eax, 4

.text:00401228 pop     ecx

.text:00401229 jnz     loc_4012CF

其中Hi_hDlg由下述交叉引用的赋值点上下文可知为注册对话框句柄

00401179 mov     Hi_hDlg, eax

上述代码获取KeyEdit框的注册key存放于char loc_key[0x15]中,其中key长度限定为4 

(2)

.text:00401229 jnz     loc_4012CF

.text:0040122F push    30h

.text:00401231 pop     ecx

.text:00401232 cmp     [ebp+loc_key], cl

.text:00401235 jz      loc_4012CF

.text:0040123B cmp     [ebp+loc_key+1], cl

.text:0040123E jz      loc_4012CF

.text:00401244 cmp     [ebp+loc_key+2], cl

.text:00401247 jz      loc_4012CF

.text:0040124D cmp     [ebp+loc_key+3], cl

.text:00401250 jz      short loc_4012CF

.text:00401252 cmp     [ebp+loc_key], 31h

.text:00401256 jnz     short loc_4012CF

.text:00401258 cmp     [ebp+loc_key+1], 35h

.text:0040125C jnz     short loc_4012CF

紧接代码(1),代码(2)要求 loc_key[i]!="0",其中i=0,1,2,3

其loc_key[0]="1" (0x31); loc_key[1] = "5" (0x35)

(3)

.text:0040126B                 movsx   eax, [ebp+loc_key+2]

.text:0040126F                 sub     eax, ecx

.text:00401271                 mov     [ebp+var_4], eax

.text:00401274                 movsx   eax, [ebp+loc_key]

.text:00401278                 fild    [ebp+var_4]

.text:0040127B                 sub     eax, ecx

.text:0040127D                 mov     [ebp+var_4], eax

.text:00401280                 movsx   eax, [ebp+loc_key+1]

.text:00401284                 fild    [ebp+var_4]

.text:00401287                 sub     eax, ecx

.text:00401289                 mov     [ebp+var_4], eax

.text:0040128C                 fidiv   [ebp+var_4]

.text:0040128F                 movsx   eax, [ebp+loc_key+3]

.text:00401293                 sub     eax, ecx

.text:00401295                 mov     [ebp+var_4], eax

.text:00401298                 fsubp   st(1), st

.text:0040129A                 fimul   [ebp+var_4]

.text:0040129D                 fmul    ds:flt_40711C

.text:004012A3                 fstp    [ebp+var_4]

//省略无关代码

.text:004012B3                 fld     [ebp+var_4]

.text:004012B6                 fcomp   ds:flt_407118

紧接代码(2),代码(3)要求下述等式成立

等式1>>  (key[2] - key[0]/key[1])*key[3]*16.0=384.0

其中key[0~3]分别为loc_key[0~3]数字字符对应的数值,即

key[0] = 1

key[1] = 5

key[0],key[1]带入等式1并化简得到

等式2>> (key[2] - 0.2)*key[3]=24.0

假定key[2]取1到9,可遍历得到相应的key[3]值

[24.0/(i-0.2) for i in xrange(1,10)]

[30.0, 13.333333333333332, 8.571428571428571, 6.315789473684211, 5.0, 4.137931034482759, 3.5294117647058822, 3.076923076923077, 2.727272727272727]

由于key[3]为字符ASCII值减去0x30所得,即key[3] = 30.0 或 5.0  (相应地,key[2]=1 或 5)

可以得到两个有效key([1,5,5,5] 或 [1,5,1,30]),相应的key字符串为 "1555","151N"

0x06

题外,_WinMain@16 函数体逻辑如下

(1)窗体类"myWindowClass"注册,响应行数Hi_wndclass_fnWndProc_sub_401000

hIcon = windll.user32.LoadIconA(hInstance,0x65)

hCursor  = windll.user32.LoadCursorA(0,0x7F00)

WNDCLASSEXA     struc ; (sizeof=0x30, align=0x4)

00000000 cbSize          dd 0x30

00000004 style           dd 0

00000008 lpfnWndProc     dd Hi_wndclass_fnWndProc_sub_401000

0000000C cbClsExtra      dd NULL

00000010 cbWndExtra      dd NULL

00000014 hInstance       dd hInstance

00000018 hIcon           dd hIcon

0000001C hCursor         dd hCursor

00000020 hbrBackground   dd 0x10

00000024 lpszMenuName    dd NULL

00000028 lpszClassName   dd "myWindowClass"

0000002C hIconSm         dd hIcon

WNDCLASSEXA     ends

windll.user32.RegisterClassExA()

SM_CXSCREEN=0

SM_CYSCREEN=1

hWnd = windll.user32.CreateWindowExA(

    0,//dwExStyle

    "myWindowClass",

    "PEDIY CTF 2017",//WindowName

    0x8A0000,//dwStyle

    windll.user32.GetSystemMetrics(SM_CXSCREEN.0)/2-100,//X

    windll.user32.GetSystemMetrics(SM_CYSCREEN.1)/2-100,//Y

    0xFA,//nWith = 250

    0xB4,//nHeight = 180

    0,//hWndParent

    0,//hMenu

    hInstance,

    0,//lpParam

  )

(2)子对话窗体(resId:0x65)居中显示,响应函数Hi_DialogFunc_sub_401041

hDlg = windll.user32.CreateDialogParamA(

  hInstance

  0x65,//lpTemplateName

  hWnd,//hWndParent

  Hi_DialogFunc_sub_401041,//lpDialogFunc

  0,//dwInitParam

  )

windll.user32.SetWindowPos(

  hDlg,

  hWnd //hWndInsertAfter

  0,//X

  0,//Y

  0,//cx

  0,//cy

  uFlags,//0x43 SWP_SHOWWINDOW.0x0040 SWP_NOSIZE.1 SWP_NOMOVE.2

  }

windll.user32.ShowWindow(hWnd)

windll.user32.UpdateWindow(hWnd)

(3) 通过IsDiagloMessageA使得父、子响应函数

Hi_wndclass_fnWndProc_sub_401000与Hi_DialogFunc_sub_401041各司其职。

while windll.user32.GetMessageA(

  &Msg,

  0,//hWnd

  0,//wMsgFilterMin

  0,//wMsgFilterMax

  ):

  if not windll.user32.IsDiagloMessageA(hDlg,&Msg):

    windll.user32.TranslateMessage(&Msg)

    windll.user32.DispatchMessageA(&Msg)



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

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