查看文件,发现UPX壳,先脱壳。
拖入IDA,查看字符串。发现了input flag
点进去看看,跟进到 sub_411BD0 ,查看伪C代码。
int sub_411BD0()
{
char v1; // [sp+Ch] [bp-C0h]@1
memset(&v1, 0xCCu, 0xC0u);
printf("1111111111111111111111111111111111111111111111111111111111111111111111111111111\n*******************************************************************************\n************** ****************************************************\n************** ******** ********************* *************\n************** ********* ********************* ***************************\n************** ********* ********************* ***************************\n************** ********* ********************* ***************************\n************** ******* ********************** ***************************\n************** **** ************************* ***************************\n************** * *************************** **************\n************** *** ************************* ***************************\n************** ****** *********************** ***************************\n************** ******** ********************* ***************************\n************** ********** ******************* ***************************\n************** *********** ***************** *************\n*******************************************************************************\n1111111111111111111111111111111111111111111111111111111111111111111111111111111\n");
sub_41116D();
printf("input flag:\n");
sub_41116D();
scanf("%36s", &Source);
sub_41116D();
return sub_41116D();
}
跟踪进去看了半天,还真没啥思路,不太像main函数,尝试向前跟踪。
找到了sub_411C70,查看
int sub_411C70()
{
char v1; // [sp+Ch] [bp-D8h]@1
HANDLE v2; // [sp+D0h] [bp-14h]@1
HANDLE hObject; // [sp+DCh] [bp-8h]@1
memset(&v1, 0xCCu, 0xD8u);
sub_4110FF();
CreateMutexW(0, 0, 0);
::hObject = (HANDLE)sub_41116D();
j_strcpy(Dest, &Source);
CreateThread(0, 0, StartAddress, 0, 0, 0);
hObject = (HANDLE)sub_41116D();
CreateThread(0, 0, sub_41119F, 0, 0, 0);
v2 = (HANDLE)sub_41116D();
CloseHandle(hObject);
sub_41116D();
CloseHandle(v2);
sub_41116D();
while ( dword_418008 != -1 )
;
sub_411190();
CloseHandle(::hObject);
sub_41116D();
return sub_41116D();
}
多线程,先看看 sub_4110FF()
int sub_4110FF(void)
{
return sub_411BD0();
}
就是刚才的那个sub_411BD0,在这里面输入Source,之后把Source赋给Dest,然后创建一个新线程,里面是StartAddress,跟踪进去。
void __stdcall StartAddress_0(int a1)
{
int v1; // eax@2
int v2; // eax@3
int v3; // eax@4
int v4; // [sp+0h] [bp-CCh]@2
char v5; // [sp+Ch] [bp-C0h]@1
memset(&v5, 0xCCu, 0xC0u);
while ( 1 )
{
v1 = WaitForSingleObject(hObject, 0xFFFFFFFF);
sub_41116D(&v4 == &v4, v1);
if ( dword_418008 > -1 )
{
sub_41112C(&Source, dword_418008);
--dword_418008;
Sleep(0x64u);
sub_41116D(&v4 == &v4, v2);
}
v3 = ReleaseMutex(hObject);
sub_41116D(&v4 == &v4, v3);
}
}
dword_418008为1Dh,每循环一次,dword_418008都减1,当dword_418008>-1时,把Source和dword_418008当作sub_41112C函数的参数,sub_41112C进去之后是sub_411940,但是我这里点不进去,尝试查看一下汇编,发现爆红处,尝试NOP掉。
这样就可以了。
void __cdecl sub_411940(int a1, int a2)
{
char v2; // [sp+Ch] [bp-CCh]@1
char v3; // [sp+D3h] [bp-5h]@1
memset(&v2, 0xCCu, 0xCCu);
v3 = *(_BYTE *)(a2 + a1);
if ( v3 >= 97 && v3 <= 122 || v3 >= 65 && v3 <= 90 )
{
if ( v3 < 97 || v3 > 122 )
*(_BYTE *)(a2 + a1) = off_418000[0][*(_BYTE *)(a2 + a1) - 38];
else
*(_BYTE *)(a2 + a1) = off_418000[0][*(_BYTE *)(a2 + a1) - 96];
sub_41116D();
JUMPOUT(loc_411A03);
}
exit(0);
}
其中off_418000=QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm
这个其实就是一个加密函数,将source进行加密。
若v3为非小写,则:
*(_BYTE *)(a2 + a1) = off_418000[0][*(_BYTE *)(a2 + a1) - 38];
否则,则:
*(_BYTE *)(a2 + a1) = off_418000[0][*(_BYTE *)(a2 + a1) - 96];
第二个线程,跟进函数查看:
void __stdcall sub_411B10(int a1)
{
int v1; // eax@2
int v2; // eax@3
int v3; // eax@4
int v4; // [sp+0h] [bp-CCh]@2
char v5; // [sp+Ch] [bp-C0h]@1
memset(&v5, 0xCCu, 0xC0u);
while ( 1 )
{
v1 = WaitForSingleObject(hObject, 0xFFFFFFFF);
sub_41116D(&v4 == &v4, v1);
if ( dword_418008 > -1 )
{
Sleep(0x64u);
sub_41116D(&v4 == &v4, v2);
--dword_418008;
}
v3 = ReleaseMutex(hObject);
sub_41116D(&v4 == &v4, v3);
}
}
他能做的主要是让dword_418008-1。
两个线程会交替运行,这样会导致加密函数变成一个隔一个加密,这个也可以看成奇数加密,偶数不加密
最后,调用sub_411880这个函数,同理,NOP掉爆红部分。
跟进查看发现:
void sub_411880()
{
int v0; // eax@6
int v1; // eax@6
int v2; // [sp+0h] [bp-D8h]@6
char v3; // [sp+Ch] [bp-CCh]@1
int i; // [sp+D0h] [bp-8h]@1
memset(&v3, 0xCCu, 0xCCu);
for ( i = 0; i < 29; ++i )
{
if ( *(&Source + i) != off_418004[i] )
exit(0);
}
v0 = printf("\nflag{%s}\n\n", Dest);
v1 = sub_41116D(&v2 == &v2, v0);
sub_41116D(1, v1);
JUMPOUT(loc_411911);
}
其中off_418004为TOiZiZtOrYaToUwPnToBsOaOapsyS,即将Source和此字符串相比较
然后写脚本的时候卡住了……