溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

DDCTF2019兩個(gè)逆向分別是什么

發(fā)布時(shí)間:2022-01-17 10:52:51 來(lái)源:億速云 閱讀:170 作者:柒染 欄目:網(wǎng)絡(luò)安全

這篇文章的內(nèi)容主要圍繞DDCTF2019兩個(gè)逆向分別是什么進(jìn)行講述,文章內(nèi)容清晰易懂,條理清晰,非常適合新手學(xué)習(xí),值得大家去閱讀。感興趣的朋友可以跟隨小編一起閱讀吧。希望大家通過(guò)這篇文章有所收獲!

01Confused

首先參考鏈接 https://www.52pojie.cn/forum.php?mod=viewthread&tid=860237&page=1

首先分析到這個(gè)sub_1000011D0是關(guān)鍵函數(shù)是沒(méi)有什么問(wèn)題的,直接shift+f12定位DDCTF的字符串就到了這一部分邏輯

if ( (unsigned int)sub_1000011D0(*((__int64 *)&v14 + 1)) == 1 )

   objc_msgSend(v17, "onSuccess");

else

   objc_msgSend(v17, "onFailed");

跟進(jìn)去以后發(fā)現(xiàn)

__int64 __fastcall sub_1000011D0(__int64 a1)

{

char v2; // [rsp+20h] [rbp-C0h]

 __int64 v3; // [rsp+D8h] [rbp-8h]

 v3 = a1;

 memset(&v2, 0, 0xB8uLL);

 sub_100001F60(&v2, a1);

return (unsigned int)sub_100001F00(&v2);

}

這個(gè)函數(shù)首先分配了一個(gè)0xb8大小的空間,然后填充為0x00,然后把這個(gè)空間傳入了一個(gè)sub_100001F60函數(shù) 跟進(jìn)去

_int64 __fastcall sub_100001F60(__int64 a1, __int64 a2)

{

 *(_DWORD *)a1 = 0;

 *(_DWORD *)(a1 + 4) = 0;

 *(_DWORD *)(a1 + 8) = 0;

 *(_DWORD *)(a1 + 12) = 0;

 *(_DWORD *)(a1 + 16) = 0;

 *(_DWORD *)(a1 + 176) = 0;

 *(_BYTE *)(a1 + 32) = 0xF0u;

 *(_QWORD *)(a1 + 40) = sub_100001D70;

 *(_BYTE *)(a1 + 48) = 0xF1u;

 *(_QWORD *)(a1 + 56) = sub_100001A60;

 *(_BYTE *)(a1 + 64) = 0xF2u;

 *(_QWORD *)(a1 + 72) = sub_100001AA0;

 *(_BYTE *)(a1 + 80) = 0xF4u;

 *(_QWORD *)(a1 + 88) = sub_100001CB0;

 *(_BYTE *)(a1 + 96) = 0xF5u;

 *(_QWORD *)(a1 + 104) = sub_100001CF0;

 *(_BYTE *)(a1 + 112) = 0xF3u;

 *(_QWORD *)(a1 + 120) = sub_100001B70;

 *(_BYTE *)(a1 + 128) = 0xF6u;

 *(_QWORD *)(a1 + 136) = sub_100001B10;

 *(_BYTE *)(a1 + 144) = 0xF7u;

 *(_QWORD *)(a1 + 152) = sub_100001D30;

 *(_BYTE *)(a1 + 160) = 0xF8u;

 *(_QWORD *)(a1 + 168) = sub_100001C60;

 qword_100003F58 = malloc(0x400uLL);

return __memcpy_chk((char *)qword_100003F58 + 48, a2, 18LL, -1LL);

}

首先先按H把-16這些改成 unsigned_int8類型,看著方便。 這里對(duì)照前面那個(gè)文章里的看,就是在對(duì)vm_cpu結(jié)構(gòu)體進(jìn)行初始化,前6個(gè)四字節(jié)的顯然是寄存器,后幾個(gè)是綁定虛擬機(jī)字節(jié)碼和字節(jié)碼對(duì)應(yīng)的函數(shù) 這里可以切換到structures窗口按insert創(chuàng)建一個(gè)結(jié)構(gòu)體,這樣來(lái)更清晰的看代碼 首先要對(duì)下面初始化的結(jié)構(gòu)體和opcode對(duì)應(yīng)的每個(gè)函數(shù)簡(jiǎn)要分析 第一個(gè)0xF0虛擬機(jī)指令對(duì)應(yīng)的函數(shù)

_int64 __fastcall sub_100001D70(__int64 a1)

{

 __int64 result; // rax

signed int *v2; // [rsp+Ch] [rbp-18h]

 v2 = (signed int *)(*(_QWORD *)(a1 + 24) + 2LL);

switch ( *(unsigned __int8 *)(*(_QWORD *)(a1 + 24) + 1LL) )

 {

case 0x10u:

     *(_DWORD *)a1 = *v2;

break;

case 0x11u:

     *(_DWORD *)(a1 + 4) = *v2;

break;

case 0x12u:

     *(_DWORD *)(a1 + 8) = *v2;

break;

case 0x13u:

     *(_DWORD *)(a1 + 12) = *v2;

break;

case 0x14u:

     *(_DWORD *)a1 = *((char *)qword_100003F58 + *v2);

break;

default:

break;

 }

 result = a1;

 *(_QWORD *)(a1 + 24) += 6LL;

return result;

}

首先可以看到每個(gè)函數(shù)中一開始都在引用 (_QWORD*)(a1+24),于是猜測(cè)這是指令指針寄存器,在structure窗口中先創(chuàng)建結(jié)構(gòu)體給這個(gè)偏移處的qword*取個(gè)名字叫myeip

可以看到v2是虛擬機(jī)指令指針寄存器指向的地方后面第二個(gè)字節(jié)的內(nèi)容,然后有一個(gè)switch結(jié)構(gòu),是在判斷虛擬機(jī)指令后面第一個(gè)字節(jié)指定的是哪個(gè)虛擬機(jī)寄存器,然后將v2賦值到寄存器里,如果是0x14的話就把 *((char*)qword_100003F58+*v2)賦值給第一個(gè)寄存器,顯然這qword100003F58相當(dāng)于虛擬機(jī)的棧,然后函數(shù)負(fù)責(zé)移動(dòng)指令指針寄存器,這個(gè)函數(shù)對(duì)應(yīng)的虛擬機(jī)指令占六個(gè)字節(jié),所以在最后有 *(_QWORD*)(a1+24)+=6LL;,所以這個(gè)函數(shù)的功能就是把一個(gè)立即數(shù)傳入虛擬機(jī)的一個(gè)寄存器中,給他取個(gè)名字叫movreg_imm,方便后面查看

然后第二個(gè)0xF1對(duì)應(yīng)的函數(shù)

__int64 __fastcall sub_100001A60(__int64 a1)

{

 __int64 result; // rax

 result = (unsigned int)(*(_DWORD *)(a1 + 4) ^ *(_DWORD *)a1);

 *(_DWORD *)a1 = result;

 ++*(_QWORD *)(a1 + 24);

return result;

}

可以看到他把前兩個(gè)寄存器里的值進(jìn)行異或然后又把結(jié)果放到了第一個(gè)寄存器中,同樣的這個(gè)虛擬機(jī)指令占一個(gè)字節(jié),此函數(shù)負(fù)責(zé)將指令指針寄存器加1字節(jié)

0xF2對(duì)應(yīng)的函數(shù)和0xF6對(duì)應(yīng)的函數(shù)要結(jié)合來(lái)看

_int64 __fastcall sub_100001AA0(__int64 a1)

{

 __int64 result; // rax

 *(_DWORD *)(a1 + 16) = *(_DWORD *)a1 == *((char *)qword_100003F58 + *(unsigned __int8 *)(*(_QWORD *)(a1 + 24) + 1LL));

 result = a1;

 *(_QWORD *)(a1 + 24) += 2LL;

return result;

}

__int64 __fastcall sub_100001B10(__int64 a1)

{

 __int64 result; // rax

if ( *(_DWORD *)(a1 + 16) )

   *(_DWORD *)(a1 + 16) = 0;

else

   *(_QWORD *)(a1 + 24) += *(unsigned __int8 *)(*(_QWORD *)(a1 + 24) + 1LL);

 result = a1;

 *(_QWORD *)(a1 + 24) += 2LL;

return result;

}

可以看到0xF2中他把

*(_DWORD*)a1==*((char*)qword_100003F58+*(unsigned__int8*)(*(_QWORD*)(a1+24)+1LL));這個(gè)表達(dá)式的結(jié)果放到了 *(_DWORD*)(a1+16)里,0xF6中他有根據(jù) *(_DWORD*)(a1+16)移動(dòng)eip指令指針寄存器,這就很明顯了,這個(gè)寄存器的功能就是標(biāo)志寄存器,存放對(duì)比的結(jié)果,然后后面一個(gè)函數(shù)就是條件跳轉(zhuǎn)指令了

然后0xF4

_int64 __fastcall sub_100001CB0(__int64 a1)

{

 __int64 result; // rax

 result = (unsigned int)(*(_DWORD *)(a1 + 4) + *(_DWORD *)a1);

 *(_DWORD *)a1 = result;

 ++*(_QWORD *)(a1 + 24);

return result;

}

很明顯的看出這個(gè)實(shí)在做加法運(yùn)算,把前兩個(gè)寄存器的值加起來(lái)放到第一個(gè)寄存器里,取個(gè)名字叫addregimm

然后0xF5

_int64 __fastcall sub_100001CF0(__int64 a1)

{

 __int64 result; // rax

 result = (unsigned int)(*(_DWORD *)a1 - *(_DWORD *)(a1 + 4));

 *(_DWORD *)a1 = result;

 ++*(_QWORD *)(a1 + 24);

return result;

}

與上面的函數(shù)類似,這個(gè)是減法,取個(gè)名字叫subregimm

跟進(jìn)0xF3對(duì)應(yīng)的函數(shù)發(fā)現(xiàn)只有一個(gè)花括號(hào),于是取名為nop

然后0xF7

__int64 __fastcall sub_100001D30(__int64 a1)

{

 __int64 result; // rax

 result = *(unsigned int *)(*(_QWORD *)(a1 + 24) + 1LL);

 *(_DWORD *)(a1 + 176) = result;

 *(_QWORD *)(a1 + 24) += 5LL;

return result;

}

可以看到他把操作數(shù)放進(jìn)了 (_DWORD*)(a1+176)處,先不管他是在干啥,先看0xF8

__int64 __fastcall sub_100001C60(__int64 a1)

{

 __int64 result; // rax

 result = sub_100001B80((unsigned int)(char)*(_DWORD *)a1, 2LL);

 *(_DWORD *)a1 = (char)result;

 ++*(_QWORD *)(a1 + 24);

return result;

}

__int64 __fastcall sub_100001B80(char a1, int a2)

{

bool v3; // [rsp+7h] [rbp-11h]

bool v4; // [rsp+Fh] [rbp-9h]

char v5; // [rsp+17h] [rbp-1h]

 v4 = 0;

if ( a1 >= 65 )

   v4 = a1 <= 90;

if ( v4 )

 {

   v5 = (a2 + a1 - 65) % 26 + 65;

 }

else

 {

   v3 = 0;

if ( a1 >= 97 )

     v3 = a1 <= 122;

if ( v3 )

     v5 = (a2 + a1 - 97) % 26 + 97;

else

     v5 = a1;

 }

return (unsigned int)v5;

}

可以看到他調(diào)用了下級(jí)函數(shù)sub100001B80,顯然這個(gè)sub100001B80函數(shù)是在對(duì)(unsigned int)(char)*(_DWORD *)a1進(jìn)行移位為2的凱撒加密,首先他通過(guò)ascii碼的范圍判斷是大寫還是小寫,以確保大小寫字母都能夠通用,然后對(duì)其進(jìn)行凱撒移位

分析完了這幾個(gè)函數(shù)和幾個(gè)寄存器以后,可以把結(jié)構(gòu)體補(bǔ)充完整了 如下 前四個(gè)就是通用用途寄存器,第五個(gè)就是標(biāo)志寄存器,第六個(gè)是指令指針寄存器,其余的函數(shù)的功能就如其名稱所示

_int64 __fastcall sub_100001F60(vm_cpu *a1, __int64 a2)

{

 a1->vm_r1 = 0;

 a1->vm_r2 = 0;

 a1->vm_r3 = 0;

 a1->vm_r4 = 0;

 a1->flag = 0;

 a1->myeip = 0;

 LOBYTE(a1->opcode_f0) = 0xF0u;

 a1->mov_reg_imm = (__int64)mov_reg_imm;

 LOBYTE(a1->opcode_f1) = 0xF1u;

 a1->xor_r1_r2 = (__int64)xor_r1_r2;

 LOBYTE(a1->opcode_f2) = 0xF2u;

 a1->cmp_r1_imm = (__int64)cmp_r1_imm;

 LOBYTE(a1->opcode_f4) = 0xF4u;

 a1->add_r1_r2 = (__int64)add_r1_r2;

 LOBYTE(a1->opcode_f5) = 0xF5u;

 a1->dec_r1_r2 = (__int64)sub_r1_r2;

 LOBYTE(a1->opcode_f3) = 0xF3u;

 a1->nop = (__int64)nop;

 LOBYTE(a1->opcode_f6) = 0xF6u;

 a1->jz_imm = (__int64)jz_imm;

 LOBYTE(a1->opcode_f7) = 0xF7u;

 a1->mov_buff_imm = (__int64)mov_buff_imm;

 LOBYTE(a1->opcode_f8) = 0xF8u;

 a1->shift_r1_2 = (__int64)shift_r1_2;

 qword_100003F58 = malloc(0x400uLL);

return __memcpy_chk((char *)qword_100003F58 + 48, a2, 18LL, -1LL);

}

現(xiàn)在返回去查看sub_100001F00函數(shù)里調(diào)用的第二個(gè)函數(shù)

__int64 __fastcall sub_100001F00(vm_cpu *a1)

{

 a1->myeip = (__int64)&loc_100001980 + 4;

while ( *(unsigned __int8 *)a1->myeip != 0xF3 )

   sub_100001E50(a1);

 free(qword_100003F58);

return a1->vm_r6;

}

可以看到此函數(shù)初始化了myeip指令指針寄存器將其指向 (__int64)&loc_100001980+4的地方 現(xiàn)在vm_cpu結(jié)構(gòu)體搞清楚了,就可以照著結(jié)構(gòu)體翻譯 (__int64)&loc_100001980+4處的虛擬機(jī)opcode了 這里既然我們已經(jīng)了解了這些opcode的功能,其實(shí)并不需要費(fèi)力去提取出代碼執(zhí)行或者寫腳本一句一句翻譯了 他就是把一個(gè)立即數(shù)裝入r1中,然后判斷大小寫,對(duì)其進(jìn)行凱撒移位,我們直接在idapython里寫一句腳本便出來(lái)了

"".join([chr(0x41+(int(i[-2:],16)+2-0x41)%26) if int(i[-2:],16)<0x61 else chr(0x61+(int(i[-2:],16)+2-0x61)%26) for i in re.findall("f010..",get_bytes(0x100001984,3000).encode("hex"))])

DDCTF2019兩個(gè)逆向分別是什么

當(dāng)然也可以寫個(gè)腳本把整個(gè)虛擬機(jī)字節(jié)碼全部翻譯出來(lái),鑒于比賽時(shí)的時(shí)間限制,如今比賽已停止,可以看一下 首先可以用get_bytes(0x100001984,3000,0).encode("hex")把虛擬機(jī)字節(jié)碼給提取出來(lái),也可以用lazyida插件 然后解析代碼如下

import re

loc_100001980="f01066000000f8f230f6c1f01063000000f8f231f6b6f0106a000000f8f232f6abf0106a000000f8f233f6a0f0106d000000f8f234f695f01057000000f8f235f68af0106d000000f8f236f67ff01073000000f8f237f674f01045000000f8f238f669f0106d000000f8f239f65ef01072000000f8f23af653f01052000000f8f23bf648f01066000000f8f23cf63df01063000000f8f23df632f01044000000f8f23ef627f0106a000000f8f23ff61cf01079000000f8f240f611f01065000000f8f241f606f701000000f3f700000000f35dc30f1f840000000000554889e548897df8488b7df88b078945f4488b7df88b47048945f08b45f43345f0488b7df88907488b7df8488b4f184883c10148894f185dc30f1f8000000000554889e548897df8488b7df88b078945f4488b7df8488b7f180fb64701488b3d942400004863c84801cf48897de88b45f4488b4de80fbe1139d00f8510000000488b45f8c7401001000000e90b000000488b45f8c7401000000000488b45f8488b48184883c102488948185dc30f1f00554889e548897df8488b7df8488b7f188a47018845f7488b7df8837f10000f851b0000000fb645f7488b4df8488b51184863f04801f248895118e90b000000488b45f8c7401000000000488b45f8488b48184883c102488948185dc30f1f4000554889e548897df85dc3660f1f440000554889e54088f88845fe8975f831c088c10fbe45fe83f841884df70f8c0d0000000fbe45fe83f85a0f9ec1884df78a45f7a8010f8505000000e929000000b81a0000000fbe4dfe83e941034df88945f089c8998b4df0f7f983c2414088d6408875ffe965000000e90000000031c088c10fbe45fe83f861884def0f8c0d0000000fbe45fe83f87a0f9ec1884def8a45efa8010f8505000000e929000000b81a0000000fbe4dfe83e961034df88945e889c8998b4de8f7f983c2614088d6408875ffe9060000008a45fe8845ff0fbe45ff5dc366666666662e0f1f840000000000554889e54883ec10be0200000048897df8488b7df88b0788c1884df70fbe7df7e8fbfeffff0fbef0488b55f88932488b55f84c8b42184983c0014c8942184883c4105dc36666662e0f1f840000000000554889e548897df8488b7df88b078945f4488b7df88b47048945f08b45f40345f0488b7df88907488b7df8488b4f184883c10148894f185dc30f1f8000000000554889e548897df8488b7df88b078945f4488b7df88b47048945f08b45f42b45f0488b7df88907488b7df8488b4f184883c10148894f185dc30f1f8000000000554889e548897df8488b7df8488b7f184883c70148897df0488b7df08b07488b7df88987b0000000488b7df8488b4f184883c10548894f185dc3660f1f440000554889e548897df8488b7df8488b7f1848ffc748897df0488b7df8488b7f184883c70248897de8488b7df00fb60783c0f089c783e80448897de08945dc0f8773000000488d057e000000488b4de0486314884801c2ffe2488b45e88b08488b45f88908e94e000000488b45e88b08488b45f8894804e93c000000488b45e88b08488b45f8894808e92a000000488b45e88b08488b45f889480ce918000000488b0543210000488b4de84863090fbe1408488b45f88910488b45f8488b48184883c106488948185dc38fffffffa0ffffffb2ffffffc4ffffffd6ffffff0f1f4000554889e54883ec2048897df8c745f400000000c745f00000000031c088c1837df400884def0f850a000000837df0090f9cc08845ef8a45efa8010f8505000000e963000000488b45f8488b40180fb608488b45f84883c020486355f048c1e2044801d00fb63039f10f852c000000c745f401000000488b45f84883c02048634df048c1e1044801c8488b4008488b4df84889cfffd0e9090000008b45f083c0018945f0e972ffffff4883c4205dc36690554889e54883ec10488d0571faffff4883c00448897df8488b7df848894718488b45f8488b40180fb60881f9f30000000f840e000000488b7df8e811ffffffe9dbffffff488b3d0d200000e880020000488b7df88b87b00000004883c4105dc3554889e54157415641554154534883ec18b80004000089c1488d15e1fcffff4c8d05aafdffff4c8d0d83fbffff4c8d15dcfbffff4c8d1d55fdffff488d1d0efdffff4c8d35f7faffff4c8d3db0faffff4c8d25b9fdffff48897dd0488975c8488b75d0c70600000000488b75d0c7460400000000488b75d0c7460800000000488b75d0c7460c00000000488b75d0c7461000000000488b75d0c786b000000000000000488b75d0c64620f0488b75d04c896628488b75d0c64630f1488b75d04c897e38488b75d0c64640f2488b75d04c897648488b75d0c64650f4488b75d048895e58488b75d0c64660f5488b75d04c895e68488b75d0c64670f3488b75d04c895678488b75d0c68680000000f6488b75d04c898e88000000488b75d0c68690000000f7488b75d04c898698000000488b75d0c686a0000000f8488b75d0488996a80000004889cfe82901000041bd120000004489ea48c7c1ffffffff488905941e0000488b058d1e00004883c030488b75c84889c7e8ef000000488945c04883c4185b415c415d415e415f5dc39090554889e54883ec20488d45e848897df8488975f048c745e8000000004889c74889d6e8ef00000031c989ce488d45e84889c7e8df0000004883c4205dc30f1f00554889e54883ec20488d45e848897df8488975f048c745e8000000004889c74889d6e8af00000031c989ce488d45e84889c7e89f00000041b001410fbec04883c4205dc36666662e0f1f840000000000554889e54883ec20488d45e848897df8488975f048c745e8000000004889c74889d6e85f00000031c989ce488d45e84889c7e84f0000004883c4205dc3ffff255c0e0000ff255e0e0000ff25600e0000ff25620e0000ff25640e0000ff25660e0000ff25680e0000ff256a0e0000ff256c0e0000ff256e0e0000ff25700e0000ff25720e0000ff25740e0000ff25760e0000ff25780e00004c8d1de90d00004153ff25d90d0000906819000000e9e6ffffff6862000000e9dcffffff6885000000e9d2ffffff689d000000e9c8ffffff68ba000000e9beffffff68d4000000e9b4ffffff68f2000000e9aaffffff681c010000e9a0ffffff6835010000e996ffffff684c010000e98cffffff6826000000e982ffffff683a000000e978ffffff6846000000e96effffff6854000000e964ffffff6800000000e95affffff766965774469644c6f616400736574526570726573656e7465644f626a6563743a0070776400737472696e6756616c7565006861735072656669783a006c656e67746800737562737472696e6746726f6d496e6465783a006973457175616c546f537472696e673a00737562737472696e675769746852616e67653a0055544638537472696e67006f6e4661696c6564006f6e5375636365737300616c6c6f6300696e697400736574416c6572745374796c653a00616464427574746f6e576974685469746c653a007365744d657373616765546578743a00736574496e666f726d6174697665546578743a007368617265644170706c69636174696f6e006b657957696e646f7700626567696e53686565744d6f64616c466f7257696e646f773a636f6d706c6574696f6e48616e646c65723a00636865636b436f64653a002e6378785f6465737472756374007365745077643a005f707764006973457175616c3a00636c6173730073656c6600706572666f726d53656c6563746f723a00706572666f726d53656c6563746f723a776974684f626a6563743a00706572666f726d53656c6563746f723a776974684f626a6563743a776974684f626a6563743a00697350726f78790069734b696e644f66436c6173733a0069734d656d6265724f66436c6173733a00636f6e666f726d73546f50726f746f636f6c3a00726573706f6e6473546f53656c6563746f723a0072657461696e0072656c65617365006175746f72656c656173650072657461696e436f756e74007a6f6e650068617368007375706572636c617373006465736372697074696f6e0064656275674465736372697074696f6e006170706c69636174696f6e53686f756c6454"



loc_100001980=re.findall("..",loc_100001980)




#print(loc_100001980)


a=0


code=[]


c=[


   ["f0",6,lambda x:str("mov r"+x[1]+",0x"+x[2])],


   ["f1",1,lambda x:str("xor r10,r11")],


   ["f2",2,lambda x:str("cmp r10,byte ptr ss:[0x"+x[1]+"]")],


   ["f3",1,lambda x:"nop"],


   ["f4",1,lambda x:str("add r10,r11")],


   ["f5",1,lambda x:str("sub r10,r11")],


   ["f6",2,lambda x:str("jz "+x[1])],


   ["f7",5,lambda x:str("mov buf,imm")],


   ["f8",1,lambda x:str("caesar encode r10,2")]


]


while 1:


for i in c:


if(loc_100001980[a] in i):


print(i[2](loc_100001980[a:a+i[1]]))


#print(loc_100001980[a:a+i[1]])


           a+=i[1]


break

運(yùn)行后效果如下,極大的增強(qiáng)了可讀性



mov r10,0x66


caesar encode r10,2


cmp r10,byte ptr ss:[0x30]


jz c1


mov r10,0x63


caesar encode r10,2


cmp r10,byte ptr ss:[0x31]


jz b6


mov r10,0x6a


caesar encode r10,2


cmp r10,byte ptr ss:[0x32]


jz ab


mov r10,0x6a


caesar encode r10,2


cmp r10,byte ptr ss:[0x33]


jz a0


mov r10,0x6d


caesar encode r10,2


cmp r10,byte ptr ss:[0x34]


jz 95


mov r10,0x57


caesar encode r10,2


cmp r10,byte ptr ss:[0x35]


jz 8a


mov r10,0x6d


caesar encode r10,2


cmp r10,byte ptr ss:[0x36]


jz 7f


mov r10,0x73


caesar encode r10,2


cmp r10,byte ptr ss:[0x37]


jz 74


mov r10,0x45


caesar encode r10,2


cmp r10,byte ptr ss:[0x38]


jz 69


mov r10,0x6d


caesar encode r10,2


cmp r10,byte ptr ss:[0x39]


jz 5e


mov r10,0x72


caesar encode r10,2


cmp r10,byte ptr ss:[0x3a]


jz 53


mov r10,0x52


caesar encode r10,2


cmp r10,byte ptr ss:[0x3b]


jz 48


mov r10,0x66


caesar encode r10,2


cmp r10,byte ptr ss:[0x3c]


jz 3d


mov r10,0x63


caesar encode r10,2


cmp r10,byte ptr ss:[0x3d]


jz 32


mov r10,0x44


caesar encode r10,2


cmp r10,byte ptr ss:[0x3e]


jz 27


mov r10,0x6a


caesar encode r10,2


cmp r10,byte ptr ss:[0x3f]


jz 1c


mov r10,0x79


caesar encode r10,2


cmp r10,byte ptr ss:[0x40]


jz 11


mov r10,0x65


caesar encode r10,2


cmp r10,byte ptr ss:[0x41]


jz 06


mov buff,imm


nop


mov buff,imm


nop

像這種偽代碼不能運(yùn)行,所以說(shuō)實(shí)際比賽中還是分析好了像前一個(gè)方法一樣,不一句一句翻譯,直接寫腳本解題比較快

02Obfuscating macros

ubuntu64 + gdbserver + ida64調(diào)試環(huán)境

首先main函數(shù)里關(guān)鍵的函數(shù)只有兩個(gè),一個(gè)sub4069D6一個(gè)sub4013E6,先跟進(jìn)第一個(gè)函數(shù),在所有傳入我們輸入的變量的地方下斷點(diǎn) 然后配置好遠(yuǎn)程gdb調(diào)試器,f9運(yùn)行起來(lái),隨手輸入ABCD,ida中觸發(fā)斷點(diǎn),首先先觀察寄存器的值,在堆棧中找到我們輸入的字符串

然后一路f9觀察對(duì)我們輸入的字符串做了什么

f9幾次后會(huì)發(fā)現(xiàn)他把我們輸入的ABCD轉(zhuǎn)換成了0xABCD

DDCTF2019兩個(gè)逆向分別是什么

繼而我們推測(cè)下一個(gè)函數(shù)會(huì)對(duì)0xABCD進(jìn)一步處理或者與一些值進(jìn)行比較,于是刪除所有其他的斷點(diǎn),在0xABCD處下內(nèi)存讀寫斷點(diǎn),然后f9運(yùn)行,就觸發(fā)了硬件斷點(diǎn)

DDCTF2019兩個(gè)逆向分別是什么

第一次 test al,al是檢測(cè)輸入是否為空,再按f9觸發(fā)第二次斷點(diǎn),會(huì)發(fā)現(xiàn)如下代碼



text:0000000000405FA3 loc_405FA3:


.text:0000000000405FA3 mov     rax, [rbp+var_220]


.text:0000000000405FAA lea     rdx, [rax+1]


.text:0000000000405FAE mov     [rbp+var_220], rdx


.text:0000000000405FB5 movzx   edx, byte ptr [rax]


.text:0000000000405FB8 mov     rax, [rbp+var_210]


.text:0000000000405FBF movzx   eax, byte ptr [rax]


.text:0000000000405FC2 mov     ecx, eax


.text:0000000000405FC4 mov     eax, edx


.text:0000000000405FC6 sub     ecx, eax


.text:0000000000405FC8 mov     eax, ecx


.text:0000000000405FCA mov     edx, eax


.text:0000000000405FCC mov     rax, [rbp+var_210]


.text:0000000000405FD3 mov     [rax], dl


.text:0000000000405FD5 mov     rax, [rbp+var_280]


.text:0000000000405FDC test    rax, rax


.text:0000000000405FDF jnz     short loc_

f8到0000000000405FC6處會(huì)發(fā)現(xiàn)他拿我們的0xAB與一個(gè)0x79進(jìn)行了對(duì)比,這樣的話我們只需要在sub這里下一個(gè)斷點(diǎn),一路f9就好了 他一開始沒(méi)有驗(yàn)證長(zhǎng)度,直接進(jìn)行了對(duì)比,只要對(duì)比到不同就退出,因?yàn)槲覀冚斎肓薃BCD,觀察到他對(duì)比一次就會(huì)退出了 這樣我們就可以每次多輸入兩個(gè)字符,并且這兩個(gè)字符只能是0到9和A到F,然后取出新的對(duì)比的字符再多輸入兩個(gè)字符直到他不在對(duì)比就得到flag了

這道題目還是說(shuō),如果沒(méi)有先調(diào)試得到的知識(shí)背景,用pintool解題也會(huì)卡殼的,因?yàn)榻?jīng)過(guò)我們的分析,發(fā)現(xiàn)第一個(gè)函數(shù)把字符串ABCD轉(zhuǎn)換成了0xABCD,這里四個(gè)字節(jié)變成了兩個(gè)字節(jié),如果用pintool解題需要兩個(gè)字符兩個(gè)字符得組合得測(cè)試,這個(gè)題目不是純正的ollvm混淆的,大體的思路就是污點(diǎn)追蹤,把所有的涉及到用戶輸入的地方都下斷點(diǎn),還有就是內(nèi)存斷點(diǎn)的使用,在必要時(shí)刻是很有用的。

感謝你的閱讀,相信你對(duì)“DDCTF2019兩個(gè)逆向分別是什么”這一問(wèn)題有一定的了解,快去動(dòng)手實(shí)踐吧,如果想了解更多相關(guān)知識(shí)點(diǎn),可以關(guān)注億速云網(wǎng)站!小編會(huì)繼續(xù)為大家?guī)?lái)更好的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI