BUUCTF RE Youngter-drive
1.查壳

upx的 去kali脱壳
2.IDA
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
HANDLE v4; // [esp+D0h] [ebp-14h]
HANDLE hObject; // [esp+DCh] [ebp-8h]
((void (*)(void))sub_4110FF)();
::hObject = CreateMutexW(0, 0, 0);
j_strcpy(Destination, &Source);
hObject = CreateThread(0, 0, StartAddress, 0, 0, 0);
v4 = CreateThread(0, 0, sub_41119F, 0, 0, 0);
CloseHandle(hObject);
CloseHandle(v4);
while ( dword_418008 != -1 )
;
sub_411190();
CloseHandle(::hObject);
return 0;
}
可以看到创建了两个进程
hObject = CreateThread(0, 0, StartAddress, 0, 0, 0);
v4 = CreateThread(0, 0, sub_41119F, 0, 0, 0);
查看SrartAddress函数
void __stdcall StartAddress_0(int a1)
{
while ( 1 )
{
WaitForSingleObject(hObject, 0xFFFFFFFF);
if ( dword_418008 > -1 )
{
sub_41112C(&Source, dword_418008);
--dword_418008;
Sleep(0x64u);
}
ReleaseMutex(hObject);
}
}
继续跟进sub_41112c函数
char *__cdecl sub_411940(int a1, int a2)
{
char *result; // eax
char v3; // [esp+D3h] [ebp-5h]
v3 = *(_BYTE *)(a2 + a1);
if ( (v3 < 97 || v3 > 122) && (v3 < 65 || v3 > 90) )
exit(0);
if ( v3 < 97 || v3 > 122 )
{
result = off_418000[0];
*(_BYTE *)(a2 + a1) = off_418000[0][*(char *)(a2 + a1) - 38];
}
else
{
result = off_418000[0];
*(_BYTE *)(a2 + a1) = off_418000[0][*(char *)(a2 + a1) - 96];
}
return result;
}
97 122是小学ascii字符a-z
这就是一个判断大小写字符,对字符进行表替换。off_418000[0]的值为QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbn
查看另一函数 sub_411B10(int a1)
void __stdcall sub_411B10(int a1)
{
while ( 1 )
{
WaitForSingleObject(hObject, 0xFFFFFFFF);
if ( dword_418008 > -1 )
{
Sleep(0x64u);
--dword_418008;
}
ReleaseMutex(hObject);
}
}
这里少了对我们输入字符的操作函数,就仅仅对dword_418008变量进行减1操作。
回到主函数最后有个sub_411190函数,打开
int sub_411880()
{
int i; // [esp+D0h] [ebp-8h]
for ( i = 0; i < 29; ++i )
{
if ( Source[i] != off_418004[i] )
exit(0);
}
return printf("\nflag{%s}\n\n", Destination);
}
然后就可以写脚本解题了。一开始索引dword_418008为29的时候要加密,那么索引i为0的时候不解密,为1的时候解密。
阅读sub_411940可以得知,我们要找到最后与Dest相比较的字符串off_418004的每一位字符在加密函数中的字符串off_418000中出现的位置,
再根据索引的奇偶,和位置+38是否大于等于65来判断是否进行解密以及如何解密。
注意off_418004字符串只有29位,而我们需要30位,所以最后要添加一位。(根据答案,最后一位字符解密后为’E’)
1 test = "TOiZiZtOrYaToUwPnToBsOaOapsyS"
2 test1 = "TOiZiZtOrYaToUwPnToBsOaOapsySy" # 随便添加一位(说随便其实也不随便)
3 key = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasd"
4 Source=""
5 for i in range(0,30):
6 if i%2==1: # 加密
7 # x = key.find(test[d]) # 会报错,out of range,test只有29位
8 x = key.find(test1[i])
9 if x+38 >= 65:
10 Source+=chr(x+38)
11 else:
12 Source+=chr(x+96)
13 else: # 不加密
14 Source+=test1[i]
15 print(Source)
flag{ThisisthreadofwindowshahaIsESE}