看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路

Editor發表於2018-12-21

第十題《俠義雙雄》在今天(12月21日)中午12:00 結束攻擊!共32支團隊攻擊成功,其中,AceHub 以1848s 攻速奪得本題第一名!

本題結束後,防守團隊排行榜如下:


看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路

最新賽況戰況一覽


第十題之後,攻擊方最新排名情況如下:

看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路


中午放題搬磚狗哭哭 繼續穩坐第一,前六名保持不變;7-10名大變動,其中  n0body 遺憾出局Top 10,111new111 進入Top 10 排行榜!


第十題 點評


crownless:

“俠義雙雄”此題原本設計了javascript解密,反彙編,字串變形,指令變形等關卡,但由於作者忽略了HTML程式碼在記憶體中很容易搜到的問題,導致題目很快被破解了。



第十題 出題團隊簡介


出題團隊: 戰神伽羅


看到解的這麼完美,我也是非常驚喜!很期待下次繼續參與,只要有機會,我會一直參與!找到組織了。


看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路


第十題 設計思路


由看雪論壇simpower  原創


看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路


設計說明:


1.首先將密碼封裝在javascript中,通過javascript將自身進行加密。

2.通過簡單的彙編程式碼變形演算法 (加減固定數值) ,將javascript程式碼編譯到可執行區域,通過指令跳轉和對硬編碼的變形對javascript程式碼進行恢復。

3.將恢復的程式碼注入到IE核心當中,並顯示出來,沒有殼。



破解思路


1.靜態文字編輯器可以看到一部分javascript程式碼。首先用od載入,搜尋字元,可以看到一部分javascript程式碼,把程式碼複製出來之後發現不完整,啟動起來之後,會將主要程式碼擦除。


看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路


看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路


看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路


2.然後在這附近下斷點,往下滾動,可以看到函式內部有一些奇怪的指令變形,這就是存放剩餘javascript的地方了:


看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路


3.在變形指令跳回處下斷,單步跟蹤之後,找到javascript的剩餘部分:


發現jmp下面有好多很大的數字,懷疑是字串做了變形,反覆對比結尾(上一張圖片),結尾有個 7F 00,估計就是字串,於是將這段資料每個位元組-7F,果然得到了ASCII碼,就是剩下的javascript程式碼。


看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路


跟前半部分組合起來就是:


eval(function(s,p,a,c,k,e,d){for(i=0;i


4.javascript解密:


用記事本編寫解密程式碼:


function jsdecode() {

var code = enc.value;

code = code.replace(/^eval/, '');

decode = eval(code);

document.write(decode);

}


儲存為html檔案,然後用瀏覽器開啟,即可解密。


得到真正的javascript程式碼:


function ckpswd() {

a = document.all.pswd.value;

if (a == "kanxueCTF2018bySimpower91") {

alert("congratulations!")

} else {

alert("wrong!<" + a + "> is not my GUID ;-)")

}

}

密碼就在裡面了。


題目執行效果:


看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路


原文連結:

https://bbs.pediy.com/thread-247387.htm



第十題  諜戰 解題思路


本題解析由看雪論壇ODPan原創。


看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路


初探


可執行檔案是Delphi編寫。


嘗試尋找checkMyFlag按鍵處理函式,作者是有意隱藏了。在錯誤提示介面有顯示“VBScript”轉而檢視指令碼資訊。


VBScript


aScriptLanguage:                        ; DATA XREF: CODE:00469349↑o

CODE:00469598 text "UTF-16LE", '',0Dh,0Ah

CODE:00469598 text "UTF-16LE", 'function alert(msg_str)',0Dh,0Ah

CODE:00469598 text "UTF-16LE", 'MsgBox msg_str,vbOKOnly + vbExclamation + vbApplica'

CODE:00469598 text "UTF-16LE", 'tionModal,""',0Dh,0Ah

CODE:00469598 text "UTF-16LE", 'End Function',0Dh,0Ah

CODE:00469598 text "UTF-16LE", '

',0

CODE:004696B8 dword_4696B8 dd 88000101h, 74697277h, 6E6C65h, 0FFFFFFFFh, 8Eh

CODE:004696B8                                         ; DATA XREF: CODE:00469357↑o

CODE:004696CC aCenterBrBrBrIn db '

CODE:004696CC ; DATA XREF: CODE:0046939C↑o

CODE:004696CC db '>

CODE:004696CC db ';"

>',0

CODE:0046975B align 4


這裡我們可以看到,checkMyFlag相關處理和ckpswd() 和 pswd敏感資訊。


在引用aScriptLanguage處下斷點。


CODE:00469343 add     esp, 10h

CODE:00469346 lea     eax, [ebp-0Ch]

CODE:00469349 mov     edx, offset aScriptLanguage     ; "\r\nfunct"...


無意中在eax中指向的地址發現瞭如下資訊:


05432D024 00 40 00 69 00 66 00 24 00 24 00 24 00 40 00 $.@.i.f.$.$.$.@.

05432E0 69 00 73 00 24 00 24 00 24 00 40 00 6B 00 61 00 i.s.$.$.$.@.k.a.

05432F06E 00 78 00 75 00 65 00 43 00 54 00 46 00 32 00 n.x.u.e.C.T.F.2.

0543300 30 00 31 00 38 00 62 00 79 00 53 00 69 00 6D 00 0.1.8.b.y.S.i.m.

0543310 70 00 6F 00 77 00 65 00 72 00 39 00 31 00 24 00 p.o.w.e.r.9.1.$.

0543320 24 00 24 00 40 00 6D 00 79 00 24 00 24 00 24 00 $.$.@.m.y.$.$.$.

0543330 40 00 6E 00 6F 00 74 00 24 00 24 00 24 00 40 00 @.n.o.t.$.$.$.@.

0543340 70 00 73 00 77 00 64 00 24 00 24 00 24 00 40 00 p.s.w.d.$.$.$.@.

0543350 76 00 61 00 6C 00 75 00 65 00 24 00 24 00 24 00 v.a.l.u.e.$.$.$.

0543360 40 00 77 00 72 00 6F 00 6E 00 67 00 24 00 24 00 @.w.r.o.n.g.$.$.

0543370 24 00 27 00 2E 00 73 00 70 00 6C 00 69 00 74 00 $.'...s.p.l.i.t.

邏輯看上去是個判斷pw指令碼,使用“kanxueCTF2018bySimpower91”測試了一下,居然通過了。肯定是個非預期了。


繼續探索


還原始碼


這個指令碼從何而來呢?在引用指令碼的上面存在這樣一段程式碼,其中內部還有一部分加密的資料。


DE:004691A2 loc_4691A2: ; CODE XREF: CODE:00469468↓j

CODE:004691A2 nop

CODE:004691A3 nop

CODE:004691A4 pushf

CODE:004691A5 call    sub_467ACC

CODE:004691AA mov     word ptr [esi+72928992h], ss

CODE:004691B0 mov     dl, 73h

CODE:004691B2 jz      short loc_46915E

CODE:004691B4 add     ebx, [esi+37h]

CODE:004691B7 xor     edi, [ecx+19D217FFh]

CODE:004691B7 ; ---------------------------------------------------------------------------

CODE:004691BD db 0, 0, 74h

CODE:004691C0 dd 0BA7273AAh, 4591170Bh, 0BA720006h

CODE:004691CC db 0Bh, 0AFh, 97h

CODE:004691CF dd 0FFB96AC7h

CODE:004691D3 db 97h

CODE:004691D4 dd 0FFB96AE7h

CODE:004691D8 dd 936A72h, 0BA740000h, 77F7407h, 17FFFFFDh, 979Fh, 937A72h, 72AF0000h

CODE:004691D8 dd 837Ah, 0CA17AF00h, 7C000597h, 7A72F33Bh, 83h, 17FF95AFh, 597DBh, 14EF3B7Ch

CODE:004691D8 dd 92968CF6h, 919A9289h

CODE:0046921C db 9Bh, 0FFh, 68h

CODE:0046921F dd offset aScript_0 ; "</script>"

CODE:00469223 ; ---------------------------------------------------------------------------

CODE:00469223 push    offset dword_46950C

CODE:00469228 push    offset dword_469518

CODE:0046922D lea     edx, [ebp-0B4h]

CODE:00469233 mov     eax, [ebp-8]

CODE:00469236 mov     eax, [eax+2F8h]

CODE:0046923C call    @Olectrls@TOleControl@GetOleObject$qqrv ; Olectrls::TOleControl::GetOleObject(void)


分析發現,函式467ACC() 將程式碼中的加密程式碼資料進行了解密,反彙編,重定位,動態解析執行,一條一條語句的執行。還原的程式解密了上面看到的指令碼。


467ACC()-> 467878() -> 46750C()-->467938()

int __stdcall sub_46750C(int a1, int a2, int a3, _DWORD *a4, int *a5, _DWORD *a6)

{

_DWORD *v6; // ebx

int v7; // eax

int v8; // edi

int *v10; // [esp-Ch] [ebp-37Ch]

void *v11; // [esp-8h] [ebp-378h]

int *v12; // [esp-4h] [ebp-374h]

void *v13; // [esp+0h] [ebp-370h]

int v14; // [esp+Ch] [ebp-364h]

int *v15; // [esp+10h] [ebp-360h]

char v16; // [esp+14h] [ebp-35Ch]

char v17; // [esp+24h] [ebp-34Ch]

char v18; // [esp+28h] [ebp-348h]

char v19; // [esp+128h] [ebp-248h]

char *v20; // [esp+35Ch] [ebp-14h]

int v21; // [esp+360h] [ebp-10h]

int v22; // [esp+364h] [ebp-Ch]

int v23; // [esp+368h] [ebp-8h]

int v24; // [esp+36Ch] [ebp-4h]

int savedregs; // [esp+370h] [ebp+0h]

v15 = 0;

v14 = 0;

v21 = 0;

v12 = &savedregs;

v11 = &loc_4677B2;

v10 = (int *)__readfsdword(0);

__writefsdword(0, (unsigned int)&v10);

v6 = sub_466DAC();

sub_467938((int)v6, (const void *)a2, &v16, (int)v6, &v22);

v22 = ((int (__stdcall *)(char *, int, signed int, char *, signed int, int *))v6[1036])(

&v16,

v22,

0x400000, // 反彙編,LEA ECX,[SS:EBP-74]

&v17,

4,

v10);

*a4 = v22;

v20 = (char *)(v6 + 1038);

sub_464518(v6 + 1038, &v16, v22);

*((_BYTE *)v6 + v22 + 4152) = 104;

unknown_libname_54((int)&v21, &v19);

if ( (unsigned __int8)sub_466EF8(v21, v6[10]) )

{

unknown_libname_54((int)&v21, &v18);

v24 = sub_464598(&str___15[1], v21);

v10 = &v21;

unknown_libname_58(v21);

System::__linkproc__ LStrCopy(v10);

v24 = sub_4645FC(v21);

if ( v22 - 1 >= 0 )

{

v7 = v22;

v23 = 0;

do

{

*((_BYTE *)v6 + v23++ + 4152) = 0x90u;

--v7;

}

while ( v7 );

}

v24 += v22;

}

else if ( sub_464598(&str_CALL[1], v21) == 1 )

{

unknown_libname_54((int)&v21, &v18);

if ( sub_464598(&str_FF[1], v21) != 1 )

{

v24 = sub_464598(&str___15[1], v21);

v23 = v24 - 1;

v8 = (v24 - 1) / 2;

v20 = (char *)v6 + v8 + 4152;

v10 = &v21;

unknown_libname_58(v21);

System::__linkproc__ LStrCopy(v10);

v24 = sub_4645FC(v21);

v23 = v24 + a2 - (_DWORD)(v6 + 1038);

sub_464518(v20, &v23, v22 - v8);

}

v24 = v22;

}

else

{

v24 = v22;

}

*a6 = v24;

v6[1] = v24;

v24 = a3;

v20 = (char *)v6 + v22 + 4153;

sub_464518(v20, &v24, 4u);

*((_BYTE *)v6 + v22 + 4157) = -61;

*a5 = (int)(v6 + 1038);

v6[9] = a2 + *a6;

unknown_libname_54((int)&v15, &v19);

v10 = v15;

unknown_libname_54((int)&v14, &v18);

sub_4678BC((int)v6, *a5, a2, (int)v10, v14, v22);

__writefsdword(0, (unsigned int)v1

1);

v13 = &loc_4677B9;

System::__linkproc__ LStrArrayClr((int)&v14, 2);

return System::__linkproc__ LStrClr(&v21);

}

int __fastcall sub_467938(int a1, const void *a2, void *a3, _DWORD *a4)

{

int result; // eax

if ( *(_WORD *)(a1 + 0x1062) )

return (*(int (__fastcall **)(_DWORD, const void *))(a1 + 0x1060))(*(_DWORD *)(a1 + 0x1064), a2);// 對應 467974()

sub_464518(a3, a2, 0x10u);

result = (int)a4;

*a4 = 16;

return result;

}

int __fastcall sub_467974(int a1, int a2, int a3, _DWORD *a4)

{

int v4; // ecx

char v5; // zf

_DWORD *v6; // eax

unsigned int v8; // [esp+8h] [ebp-20h]

void *v9; // [esp+Ch] [ebp-1Ch]

int *v10; // [esp+10h] [ebp-18h]

int v11; // [esp+20h] [ebp-8h]

int v12; // [esp+24h] [ebp-4h]

int savedregs; // [esp+28h] [ebp+0h]

v11 = 0;

v10 = &savedregs;

v9 = &loc_467A18;

v8 = __readfsdword(0);

__writefsdword(0, (unsigned int)&v8);

*a4 = 16;

v12 = a3;

v4 = 0;

do

{

*(_BYTE *)(v12 + v4) = ~*(_BYTE *)(a2 + v4);

++v4;

}

while ( v4 != 16 );

getInsStr(v12 + 2, (int)&v11);// 獲取指令opcode字串

System::__linkproc__ LStrCmp(v11, &str_simvmend[1]);

if ( v5 )

{

v6 = sub_466DAC();

v6[3] = v6[9];

}

__writefsdword(0, v8);

v10 = (int *)&loc_467A1F;

return System::__linkproc__ LStrClr(&v11);

}

467974()函式將0x4691AF所在資料(加密的程式碼)與0xFF異或解密,每次解密16個位元組。如上所述經過了解密,反彙編,重定位的過程,組織好了一條彙編指令。


指令準備好了,而指令又在那裡執行的呢?


int __usercall sub_467878@(int a1@, int a2@, int a3@, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14)

{

unsigned int v14; // et0

int (__fastcall *v15)(unsigned int *, unsigned int); // ST10_4

unsigned int v17; // [esp+14h] [ebp-2Ch]

int v18; // [esp+30h] [ebp-10h]

void **v19; // [esp+34h] [ebp-Ch]

int *v20; // [esp+38h] [ebp-8h]

int v21; // [esp+3Ch] [ebp-4h]

unsigned int vars0; // [esp+40h] [ebp+0h]

void *retaddr; // [esp+44h] [ebp+4h]

vars0 = a3;

v21 = a2;

v20 = (int *)&vars0;

v19 = &retaddr;

v18 = a1;

v14 = __readeflags();

*(_DWORD *)(a13 + 40) = retaddr;

sub_46750C(a13, a14, a12, &v20, (int *)&v19, &v18);

vars0 = v17;

__writeeflags(v17);

__writeeflags(v17);

return v15(&vars0, v14); //jmp     [esp-4+var_3C]

執行解密後的單條指令

}


我們可以看到EIP跳轉到0xA4038執行了一條指令,然後返回到0x467B10:


000A4038 8D 4D 8C lea  ecx, [ebp-74h]

000A403B 68 10 7B 46 00 push offset loc_467B10

:000A4040 C3 retn



繼續下一條。


所有加密程式碼還原後如下:


004691B2 8B 55 FC mov  edx, [ebp-4]

CODE:004691B0 ; ---------------------------------------------------------------------------

CODE:004691B1 8C db 8Ch

CODE:004691B2 ; ---------------------------------------------------------------------------

CODE:004691B2 8B 55 FC mov  edx, [ebp-4]

CODE:004691B5 A1 C8 CC 46 00mov  eax, ds:dword_46CCC8

CODE:004691BA E8 2D E6 FF FF call sub_4677EC

CODE:004691BF 8B 55 8C mov  edx, [ebp-74h]

CODE:004691C2 8D 45 F4 lea  eax, [ebp-0Ch]

CODE:004691C5 E8 6E BA F9 FF call @System@@WStrFromLStr$qqrr17System@WideStringx17System@AnsiString ; System::__linkproc__ WStrFromLStr(System::WideString &,System::AnsiString)

CODE:004691CA 8D 45 F4 lea  eax, [ebp-0Ch]

CODE:004691CD 50push eax

CODE:004691CE 68 38 95 46 00push offset dword_469538

CODE:004691D3 68 18 95 46 00push offset dword_469518

CODE:004691D8 8D 95 6C FF FF FF  lea  edx, [ebp-94h]

CODE:004691DE 8B 45 F8 mov  eax, [ebp-8]

CODE:004691E1 8B 80 F8 02 00 00 mov  eax, [eax+2F8h]

CODE:004691E7 E8 60 68 FF FF call @Olectrls@TOleControl@GetOleObject$qqrv ; Olectrls::TOleControl::GetOleObject(void)

CODE:004691EC 8D 85 6C FF FF FF  lea  eax, [ebp-94h]

CODE:004691F2 50push eax

CODE:004691F3 8D 85 7C FF FF FF  lea  eax, [ebp-84h]

CODE:004691F9 50push eax

CODE:004691FA E8 35 68 FA FF call @Variants@@DispInvoke$qp8TVarDatarx8TVarDatap16System@TCallDescpv ; Variants::__linkproc__ DispInvoke(TVarData *,TVarData &,System::TCallDesc *,void *)

CODE:004691FF 83 C4 0C add  esp, 0Ch

CODE:00469202 8D 85 7C FF FF FF  lea  eax, [ebp-84h]

CODE:00469208 50push eax

CODE:00469209 6A 00 push 0

CODE:0046920B E8 24 68 FA FF call @Variants@@DispInvoke$qp8TVarDatarx8TVarDatap16System@TCallDescpv ; Variants::__linkproc__ DispInvoke(TVarData *,TVarData &,System::TCallDesc *,void *)

CODE:00469210 83 C4 10add  esp, 10h

CODE:00469213 EB 09 jmp  short loc_46921E short loc_46921E



還原指令碼


還原完程式碼,繼續還原指令碼,解密後的程式碼中有個函式sub_4677EC(),該函式還原指令碼檔案。


nt __usercall sub_4677EC@(_BYTE *a1@, int a2@, int a3@, int a4@, int a5@)

{

int v5; // esi

int v6; // edx

unsigned int v8; // [esp-18h] [ebp-24h]

void *v9; // [esp-14h] [ebp-20h]

int *v10; // [esp-10h] [ebp-1Ch]

int v11; // [esp-Ch] [ebp-18h]

int v12; // [esp-8h] [ebp-14h]

int v13; // [esp-4h] [ebp-10h]

int v14; // [esp+0h] [ebp-Ch]

int v15; // [esp+4h] [ebp-8h]

_BYTE *i; // [esp+8h] [ebp-4h]

int savedregs; // [esp+Ch] [ebp+0h]

v15 = 0;

v14 = 0;

v13 = a3;

v12 = a5;

v11 = a4;

v5 = a2;

i = a1;

v10 = &savedregs;

v9 = &loc_467867;

v8 = __readfsdword(0);

__writefsdword(0, (unsigned int)&v8);

LOBYTE(a3) = *a1;

for ( i = a1 + 1; (unsigned __int8)a3 > 0x7Fu; ++i )

{

v6 = a3;

LOBYTE(v6) = a3 - 127;

unknown_libname_53(&v14, v6);

System::__linkproc__ LStrCat(&v15, v14);

LOBYTE(a3) = *i;

}

System::__linkproc__ LStrAsg(v5, v15);

__writefsdword(0, v8);

v10 = (int *)&loc_46786E;

return System::__linkproc__ LStrArrayClr(&v14, 2);

}

//加密的指令碼資料

CODE:004693F8 dword_4693F8    dd 0BFA3A3A3h, 0A3A3E5E8h, 0F2E8BFA3h, 0BFA3A3A3h, 0F7EDE0EAh

CODE:004693F8                                         ; DATA XREF: CODE:loc_469460↓o

CODE:004693F8                 dd 0D3C2E4F4h, 0B0AFB1C5h, 0D2F8E1B7h, 0EEEFECE8h, 0B8F1E4F6h

CODE:004693F8                 dd 0A3A3A3B0h, 0A3F8ECBFh, 0EDBFA3A3h, 0A3A3F3EEh, 0F2EFBFA3h

CODE:004693F8                 dd 0A3A3E3F6h, 0E0F5BFA3h, 0A3E4F4EBh, 0F6BFA3A3h, 0E6EDEEF1h

CODE:004693F8                 dd 0A6A3A3A3h, 0EBEFF2ADh, 0A6A7F3E8h, 0ABA8A6BFh, 0FCFAABAFh

CODE:004693F8                 dd 7FA8A8h

解密後的資料,就是我們開頭看到的文字內容了。

f...$$$@if$$$@is

$$$@kanxueCTF201

8bySimpower91$$$

@my$$$@not$$$@ps

wd$$$@value$$$@w

rong$$$'.split('

Flag:kanxueCTF2018bySimpower91

解密後的資料,就是我們開頭看到的文字內容了。


f...$$$@if$$$@is

$$$@kanxueCTF201

8bySimpower91$$$

@my$$$@not$$$@ps

wd$$$@value$$$@w

rong$$$'.split('

Flag:kanxueCTF2018bySimpower91


原文連結:


https://bbs.pediy.com/thread-248550.htm




第十一題【 伊甸園】正在火熱進行中

第11題/共15題

《伊甸園》將於 12月23 日中午 12:00 結束

趕緊參與進來吧~!


合作伙伴 

看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路


騰訊安全應急響應中心 


TSRC,騰訊安全的先頭兵,肩負騰訊公司安全漏洞、黑客入侵的發現和處理工作。這是個沒有硝煙的戰場,我們與兩萬多名安全專家並肩而行,捍衛全球億萬使用者的資訊、財產安全。一直以來,我們懷揣感恩之心,努力構建開放的TSRC交流平臺,回饋安全社群。未來,我們將繼續攜手安全行業精英,探索網際網路安全新方向,建設網際網路生態安全,共鑄“網際網路+”新時代。


看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路

看雪CTF.TSRC 2018 團隊賽 第十題『俠義雙雄』 解題思路




轉載請註明:轉自看雪學院



更多資訊:






相關文章