之前比赛有出现的类似题目,但是这次虚拟执行的部分强化了很多,我并没有分析出虚拟执行的部分,有点遗憾。
用OD从内存中dump出完整的html。内存搜索
unicode
"CTF 2019"就能找到了。
为了方便调试,可以把script标签里面的代码另存为一个js文件。
得到解密后的js代码,这里为了方便看,就把两个function放到一起了。
function sptWBCallback(spt_wb_id, spt_wb_name, optionstr) {
url = '#sptWBCallback:id=';
url = url + spt_wb_id + ';eventName=' + spt_wb_name;
if (optionstr)
url = url + ';params=optionstr';
location = url;
}
function ckpswd() {
key = "Simpower91";
a = document.all.pswd.value;
if (a.indexOf(key) == 0) {
l = a.length;
i = key.length;
sptWBCallback(a.substring(i, l));
} else {
alert("wrong!<" + a + "> is not my GUID ;-)");
return "1234";
}
}
function ok() {
alert("congratulations!");
}
得到flag前面的部分为"Simpower91"。
然后我们需要找到回调函数,先用IDR分析CM,导出MAP,给IDA使用(需要插件)。
int __fastcall Unit1_Tfrmcrackme_FormCreate(int a1)
{
int v1; // ebx
int v2; // edx
int v3; // eax
int v4; // eax
double v5; // ST00_8
int v6; // edx
int v7; // ecx
int v8; // edx
int v9; // eax
int v10; // edx
int v11; // edx
Teengine::TTeeFunction *v12; // eax
double v13; // ST00_8
int v14; // edx
int result; // eax
unsigned int v16; // [esp-Ch] [ebp-14h]
void *v17; // [esp-8h] [ebp-10h]
int *v18; // [esp-4h] [ebp-Ch]
int savedregs; // [esp+8h] [ebp+0h]
v1 = a1;
v18 = &savedregs;
v17 = &loc_498D75;
v16 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v16);
SHDocVw_TWebBrowser_Navigate(*(Shdocvw::TWebBrowser **)(a1 + 760));
LOBYTE(v2) = 1;
dword_49DF50 = Unit87_TVirtualMachine_Create("\x0FTVirtualMachine", v2);
v3 = dword_49DF50;
*(_DWORD *)(dword_49DF50 + 4372) = dword_49DF50;
*(_DWORD *)(v3 + 4368) = sub_477514;
v4 = ScripertJava_TScripertJava_Create((Classes::TComponent *)&cls_ScripertJava_TScripertJava);
*(_DWORD *)(v1 + 824) = v4;
*(_DWORD *)(v4 + 72) = *(_DWORD *)(v1 + 760);
sub_4969C0(v4);
HIDWORD(v5) = v1;
LODWORD(v5) = &sub_49945C; // 回调函数
ScripertJava_TScripertJava_SetOnSptWBCallBack(*(Teengine::TTeeFunction **)(v1 + 824), v5);// 设置回调函数
ScripertJava_TScripertJava_SetOnBeforeSptWBCallBack(*(_DWORD *)(v1 + 824), v6, v7, v1, (int)sub_499428);
LOBYTE(v8) = 1;
v9 = Unit91_TIHookAgent_Create(dword_4957E8, v8);
*(_DWORD *)(v1 + 832) = v9;
Iddnsserver::TIdDNTreeNode::SaveToFile(v9, 0);
sub_494694(*(_DWORD *)(*(_DWORD *)(v1 + 832) + 24), antiDebug_kernel32_IsDebuggerPresent, &str_idp[1]);
sub_494694(*(_DWORD *)(*(_DWORD *)(v1 + 832) + 24), MessageBoxW, &str_mb[1]);
LOBYTE(v10) = 1;
*(_DWORD *)(v1 + 820) = system_TObject_Create(dword_46F088, v10);
LOBYTE(v11) = 1;
v12 = (Teengine::TTeeFunction *)antiDebug_TAntiDebug_Create(&cls_antiDebug_TAntiDebug, v11, 0);
*(_DWORD *)(v1 + 828) = v12;
HIDWORD(v13) = v1;
LODWORD(v13) = sub_49978C;
antiDebug_TAntiDebug_SetOnCheckTrue(v12, v13);
antiDebug_TAntiDebug_SetOnAllCheckFalse(*(Idsyslogmessage::TIdSysLogMessage **)(v1 + 828), v14);
dword_49DF54 = sub_494898(*(_DWORD *)(*(_DWORD *)(v1 + 832) + 24), 0);
dword_49DF58 = sub_494898(*(_DWORD *)(*(_DWORD *)(v1 + 832) + 24), 1);
*(_BYTE *)(v1 + 836) = 0;
result = 0;
__writefsdword(0, v16);
return result;
}
在Unit1_Tfrmcrackme_FormCreate事件里面能看到设置的回调函数sub_49978C。因为不能使用F5,后面还是用OD动态调试,同样可以把map导入到OD。
OD载入CM(带SharpOD插件过反调试),0049978C 下断,输入 "Simpower911",点击按钮。
用处理异常的方法来跳转,单步过去。
单步出retn。
跟进call。
单步过第一个call没有问题,过第二个call时跑飞了,在单步过第一个call时,查看堆栈上面,发现一个可疑的调用。
00404734 strlen,在运行到004777E2处时对其下断。
运行到00476B8C,用OD的跟踪步过看看发生了什么。
在00476C3E处跑飞,可以在这里下断,测试一下几次后跑飞,然后在跑飞之前用跟踪步入,等OD断在strlen处。
在这条retn指令下断,继续运行。
eax出现
Simpower91后面的字符串的长度,继续单步,发现走出了回调函数。
有可能是字符串的长度不符合,然后就直接返回了,增加字符串的字数,继续测试几次,输入 “Simpower911111”的时候,寄存器的值发生明显变化了。
eax与edx较可疑,把输入后面改成2222发现eax是字符的ascii值加0x7F,那edx应该就是flag的ascii加0x7F了。
根据edx修改输入,edx的值分别为0xE0, 0xB2, 0xB1,
0xB0,最终得到flag后四位为a321。
故flag为:
Simpower91a321
为了方便调试,可以把script标签里面的代码另存为一个js文件。
得到解密后的js代码,这里为了方便看,就把两个function放到一起了。
function sptWBCallback(spt_wb_id, spt_wb_name, optionstr) {
url = '#sptWBCallback:id=';
url = url + spt_wb_id + ';eventName=' + spt_wb_name;
if (optionstr)
url = url + ';params=optionstr';
location = url;
}
function ckpswd() {
key = "Simpower91";
a = document.all.pswd.value;
if (a.indexOf(key) == 0) {
l = a.length;
i = key.length;
sptWBCallback(a.substring(i, l));
} else {
alert("wrong!<" + a + "> is not my GUID ;-)");
return "1234";
}
}
function ok() {
alert("congratulations!");
}
得到flag前面的部分为"Simpower91"。
function sptWBCallback(spt_wb_id, spt_wb_name, optionstr) {
url = '#sptWBCallback:id=';
url = url + spt_wb_id + ';eventName=' + spt_wb_name;
if (optionstr)
url = url + ';params=optionstr';
location = url;
}
function ckpswd() {
key = "Simpower91";
a = document.all.pswd.value;
if (a.indexOf(key) == 0) {
l = a.length;
i = key.length;
sptWBCallback(a.substring(i, l));
} else {
alert("wrong!<" + a + "> is not my GUID ;-)");
return "1234";
}
}
function ok() {
alert("congratulations!");
}
得到flag前面的部分为"Simpower91"。
然后我们需要找到回调函数,先用IDR分析CM,导出MAP,给IDA使用(需要插件)。
int __fastcall Unit1_Tfrmcrackme_FormCreate(int a1)
{
int v1; // ebx
int v2; // edx
int v3; // eax
int v4; // eax
double v5; // ST00_8
int v6; // edx
int v7; // ecx
int v8; // edx
int v9; // eax
int v10; // edx
int v11; // edx
Teengine::TTeeFunction *v12; // eax
double v13; // ST00_8
int v14; // edx
int result; // eax
unsigned int v16; // [esp-Ch] [ebp-14h]
void *v17; // [esp-8h] [ebp-10h]
int *v18; // [esp-4h] [ebp-Ch]
int savedregs; // [esp+8h] [ebp+0h]
v1 = a1;
v18 = &savedregs;
v17 = &loc_498D75;
v16 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v16);
SHDocVw_TWebBrowser_Navigate(*(Shdocvw::TWebBrowser **)(a1 + 760));
LOBYTE(v2) = 1;
dword_49DF50 = Unit87_TVirtualMachine_Create("\x0FTVirtualMachine", v2);
v3 = dword_49DF50;
*(_DWORD *)(dword_49DF50 + 4372) = dword_49DF50;
*(_DWORD *)(v3 + 4368) = sub_477514;
v4 = ScripertJava_TScripertJava_Create((Classes::TComponent *)&cls_ScripertJava_TScripertJava);
*(_DWORD *)(v1 + 824) = v4;
*(_DWORD *)(v4 + 72) = *(_DWORD *)(v1 + 760);
sub_4969C0(v4);
HIDWORD(v5) = v1;
LODWORD(v5) = &sub_49945C; // 回调函数
ScripertJava_TScripertJava_SetOnSptWBCallBack(*(Teengine::TTeeFunction **)(v1 + 824), v5);// 设置回调函数
ScripertJava_TScripertJava_SetOnBeforeSptWBCallBack(*(_DWORD *)(v1 + 824), v6, v7, v1, (int)sub_499428);
LOBYTE(v8) = 1;
v9 = Unit91_TIHookAgent_Create(dword_4957E8, v8);
*(_DWORD *)(v1 + 832) = v9;
Iddnsserver::TIdDNTreeNode::SaveToFile(v9, 0);
sub_494694(*(_DWORD *)(*(_DWORD *)(v1 + 832) + 24), antiDebug_kernel32_IsDebuggerPresent, &str_idp[1]);
sub_494694(*(_DWORD *)(*(_DWORD *)(v1 + 832) + 24), MessageBoxW, &str_mb[1]);
LOBYTE(v10) = 1;
*(_DWORD *)(v1 + 820) = system_TObject_Create(dword_46F088, v10);
LOBYTE(v11) = 1;
v12 = (Teengine::TTeeFunction *)antiDebug_TAntiDebug_Create(&cls_antiDebug_TAntiDebug, v11, 0);
*(_DWORD *)(v1 + 828) = v12;
HIDWORD(v13) = v1;
LODWORD(v13) = sub_49978C;
antiDebug_TAntiDebug_SetOnCheckTrue(v12, v13);
antiDebug_TAntiDebug_SetOnAllCheckFalse(*(Idsyslogmessage::TIdSysLogMessage **)(v1 + 828), v14);
dword_49DF54 = sub_494898(*(_DWORD *)(*(_DWORD *)(v1 + 832) + 24), 0);
dword_49DF58 = sub_494898(*(_DWORD *)(*(_DWORD *)(v1 + 832) + 24), 1);
*(_BYTE *)(v1 + 836) = 0;
result = 0;
__writefsdword(0, v16);
return result;
}
在Unit1_Tfrmcrackme_FormCreate事件里面能看到设置的回调函数sub_49978C。因为不能使用F5,后面还是用OD动态调试,同样可以把map导入到OD。
int __fastcall Unit1_Tfrmcrackme_FormCreate(int a1)
{
int v1; // ebx
int v2; // edx
int v3; // eax
int v4; // eax
double v5; // ST00_8
int v6; // edx
int v7; // ecx
int v8; // edx
int v9; // eax
int v10; // edx
int v11; // edx
Teengine::TTeeFunction *v12; // eax
double v13; // ST00_8
int v14; // edx
int result; // eax
unsigned int v16; // [esp-Ch] [ebp-14h]
void *v17; // [esp-8h] [ebp-10h]
int *v18; // [esp-4h] [ebp-Ch]
int savedregs; // [esp+8h] [ebp+0h]
v1 = a1;
v18 = &savedregs;
v17 = &loc_498D75;
v16 = __readfsdword(0);
__writefsdword(0, (unsigned int)&v16);
SHDocVw_TWebBrowser_Navigate(*(Shdocvw::TWebBrowser **)(a1 + 760));
LOBYTE(v2) = 1;
dword_49DF50 = Unit87_TVirtualMachine_Create("\x0FTVirtualMachine", v2);
v3 = dword_49DF50;
*(_DWORD *)(dword_49DF50 + 4372) = dword_49DF50;
*(_DWORD *)(v3 + 4368) = sub_477514;
v4 = ScripertJava_TScripertJava_Create((Classes::TComponent *)&cls_ScripertJava_TScripertJava);
*(_DWORD *)(v1 + 824) = v4;
*(_DWORD *)(v4 + 72) = *(_DWORD *)(v1 + 760);
sub_4969C0(v4);
HIDWORD(v5) = v1;
LODWORD(v5) = &sub_49945C; // 回调函数
ScripertJava_TScripertJava_SetOnSptWBCallBack(*(Teengine::TTeeFunction **)(v1 + 824), v5);// 设置回调函数
ScripertJava_TScripertJava_SetOnBeforeSptWBCallBack(*(_DWORD *)(v1 + 824), v6, v7, v1, (int)sub_499428);
LOBYTE(v8) = 1;
v9 = Unit91_TIHookAgent_Create(dword_4957E8, v8);
*(_DWORD *)(v1 + 832) = v9;
Iddnsserver::TIdDNTreeNode::SaveToFile(v9, 0);
sub_494694(*(_DWORD *)(*(_DWORD *)(v1 + 832) + 24), antiDebug_kernel32_IsDebuggerPresent, &str_idp[1]);
sub_494694(*(_DWORD *)(*(_DWORD *)(v1 + 832) + 24), MessageBoxW, &str_mb[1]);
LOBYTE(v10) = 1;
*(_DWORD *)(v1 + 820) = system_TObject_Create(dword_46F088, v10);
LOBYTE(v11) = 1;
v12 = (Teengine::TTeeFunction *)antiDebug_TAntiDebug_Create(&cls_antiDebug_TAntiDebug, v11, 0);
*(_DWORD *)(v1 + 828) = v12;
HIDWORD(v13) = v1;
LODWORD(v13) = sub_49978C;
antiDebug_TAntiDebug_SetOnCheckTrue(v12, v13);
antiDebug_TAntiDebug_SetOnAllCheckFalse(*(Idsyslogmessage::TIdSysLogMessage **)(v1 + 828), v14);
dword_49DF54 = sub_494898(*(_DWORD *)(*(_DWORD *)(v1 + 832) + 24), 0);
dword_49DF58 = sub_494898(*(_DWORD *)(*(_DWORD *)(v1 + 832) + 24), 1);
*(_BYTE *)(v1 + 836) = 0;
result = 0;
__writefsdword(0, v16);
return result;
}
在Unit1_Tfrmcrackme_FormCreate事件里面能看到设置的回调函数sub_49978C。因为不能使用F5,后面还是用OD动态调试,同样可以把map导入到OD。
OD载入CM(带SharpOD插件过反调试),0049978C 下断,输入 "Simpower911",点击按钮。
用处理异常的方法来跳转,单步过去。
单步出retn。
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2019-9-25 18:22
被梦游枪手编辑
,原因: 补第一张图