0

0

DDCTF2019两个逆向分别是什么

PHPz

PHPz

发布时间:2023-05-18 17:13:20

|

1493人浏览过

|

来源于亿速云

转载

01confused

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

首先分析到这个sub_1000011D0是关键函数是没有什么问题的,直接shift+f12定位DDCTF的字符串就到了这一部分逻辑

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

   objc_msgSend(v17, "onSuccess");

else

   objc_msgSend(v17, "onFailed");

跟进去以后发现

__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);

}

这个函数首先分配了一个0xb8大小的空间,然后填充为0x00,然后把这个空间传入了一个sub_100001F60函数 跟进去

_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);

}

首先将-16等数值转换为 unsigned_int8 类型,以便更方便地处理。 这里对照前面那个文章里的看,就是在对vm_cpu结构体进行初始化,前6个四字节的显然是寄存器,后几个是绑定虚拟机字节码和字节码对应的函数 这里可以切换到structures窗口按insert创建一个结构体,这样来更清晰的看代码 首先要对下面初始化的结构体和opcode对应的每个函数简要分析 第一个0xF0虚拟机指令对应的函数

_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;

}

首先可以看到每个函数中一开始都在引用 (_QWORD*)(a1+24),于是猜测这是指令指针寄存器,在structure窗口中先创建结构体给这个偏移处的qword*取个名字叫myeip

可以看到v2是虚拟机指令指针寄存器指向的地方后面第二个字节的内容,然后有一个switch结构,是在判断虚拟机指令后面第一个字节指定的是哪个虚拟机寄存器,然后将v2赋值到寄存器里,如果是0x14的话就把 *((char*)qword_100003F58+*v2)赋值给第一个寄存器,显然这qword100003F58相当于虚拟机的栈,然后函数负责移动指令指针寄存器,这个函数对应的虚拟机指令占六个字节,所以在最后有 *(_QWORD*)(a1+24)+=6LL;,所以这个函数的功能就是把一个立即数传入虚拟机的一个寄存器中,给他取个名字叫movreg_imm,方便后面查看

然后第二个0xF1对应的函数

__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;

}

可以看到他把前两个寄存器里的值进行异或然后又把结果放到了第一个寄存器中,同样的这个虚拟机指令占一个字节,此函数负责将指令指针寄存器加1字节

0xF2对应的函数和0xF6对应的函数要结合来看

_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));这个表达式的结果放到了 *(_DWORD*)(a1+16)里,0xF6中他有根据 *(_DWORD*)(a1+16)移动eip指令指针寄存器,这就很明显了,这个寄存器的功能就是标志寄存器,存放对比的结果,然后后面一个函数就是条件跳转指令了

然后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;

}

很明显的看出这个实在做加法运算,把前两个寄存器的值加起来放到第一个寄存器里,取个名字叫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;

}

与上面的函数类似,这个是减法,取个名字叫subregimm

跟进0xF3对应的函数发现只有一个花括号,于是取名为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;

}

可以看到他把操作数放进了 (_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;

}

可以看到他调用了下级函数sub100001B80,显然这个sub100001B80函数是在对(unsigned int)(char)*(_DWORD *)a1进行移位为2的凯撒加密,首先他通过ascii码的范围判断是大写还是小写,以确保大小写字母都能够通用,然后对其进行凯撒移位

分析完了这几个函数和几个寄存器以后,可以把结构体补充完整了 如下 前四个就是通用用途寄存器,第五个就是标志寄存器,第六个是指令指针寄存器,其余的函数的功能就如其名称所示

_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);

}

现在返回去查看sub_100001F00函数里调用的第二个函数

__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;

}

可以看到此函数初始化了myeip指令指针寄存器将其指向 (__int64)&loc_100001980+4的地方 现在vm_cpu结构体搞清楚了,就可以照着结构体翻译 (__int64)&loc_100001980+4处的虚拟机opcode了 这里既然我们已经了解了这些opcode的功能,其实并不需要费力去提取出代码执行或者写脚本一句一句翻译了 他就是把一个立即数装入r1中,然后判断大小写,对其进行凯撒移位,我们直接在idapython里写一句脚本便出来了

"".join([chr(0x41+(int(i[-2:],16)+2-0x41)%26) if int(i[-2:],16)

DDCTF2019两个逆向分别是什么

当然也可以写个脚本把整个虚拟机字节码全部翻译出来,鉴于比赛时的时间限制,如今比赛已停止,可以看一下 首先可以用get_bytes(0x100001984,3000,0).encode("hex")把虚拟机字节码给提取出来,也可以用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

运行后效果如下,极大的增强了可读性



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]

全诚商城生成HTML多用户版
全诚商城生成HTML多用户版

1、什么是店中店?店中店是全诚商多用户版的一大特色,它既是独立的个体,又具有群集功能。我们做个例子说明:假设尊贵的您现实生活中租赁了一个店面,店面空间很大,您可以把您的店面分割成很多独立空间再向别人转租,这样您可以额外获得一部分租赁费用收入,借以减少你的个人租赁费用投入,还能起到活跃销售场所的气氛,俗话说:货卖一堆吗。你租赁的店面可以完全分割成很多空间向外转租,也可以自己保留一块空间为自己销售商品

下载

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

像这种伪代码不能运行,所以说实际比赛中还是分析好了像前一个方法一样,不一句一句翻译,直接写脚本解题比较快

02Obfuscating macros

ubuntu64 + gdbserver + ida64调试环境

首先main函数里关键的函数只有两个,一个sub4069D6一个sub4013E6,先跟进第一个函数,在所有传入我们输入的变量的地方下断点 然后配置好远程gdb调试器,f9运行起来,随手输入ABCD,ida中触发断点,首先先观察寄存器的值,在堆栈中找到我们输入的字符串

然后一路f9观察对我们输入的字符串做了什么

f9几次后会发现他把我们输入的ABCD转换成了0xABCD

DDCTF2019两个逆向分别是什么

继而我们推测下一个函数会对0xABCD进一步处理或者与一些值进行比较,于是删除所有其他的断点,在0xABCD处下内存读写断点,然后f9运行,就触发了硬件断点

DDCTF2019两个逆向分别是什么

第一次 test al,al是检测输入是否为空,再按f9触发第二次断点,会发现如下代码



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]


重写后的句子: 将dl中的值存储到rax指向的内存地址中


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


.text:0000000000405FDC test    rax, rax


.text:0000000000405FDF jnz     short loc_

f8到0000000000405FC6处会发现他拿我们的0xAB与一个0x79进行了对比,这样的话我们只需要在sub这里下一个断点,一路f9就好了 他一开始没有验证长度,直接进行了对比,只要对比到不同就退出,因为我们输入了ABCD,观察到他对比一次就会退出了 这样我们就可以每次多输入两个字符,并且这两个字符只能是0到9和A到F,然后取出新的对比的字符再多输入两个字符直到他不在对比就得到flag了

这道题目还是说,如果没有先调试得到的知识背景,用pintool解题也会卡壳的,因为经过我们的分析,发现第一个函数把字符串ABCD转换成了0xABCD,这里四个字节变成了两个字节,如果用pintool解题需要两个字符两个字符得组合得测试,这个题目不是纯正的ollvm混淆的,大体的思路就是污点追踪,把所有的涉及到用户输入的地方都下断点,还有就是内存断点的使用,在必要时刻是很有用的。

相关文章

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2544

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1609

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1500

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

952

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1417

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1234

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1446

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1306

2023.11.13

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号