LuckyStar hctf2018
LuckyStar hctf2018
程序注册有TLS回调函数
char __stdcall TlsCallback_0(int a1, int a2, int a3)
{
char result; // al
HMODULE v4; // eax
HMODULE v5; // eax
HMODULE v6; // eax
int (__usercall *ptr_main)@<eax>(int@<ebp>); // esi
signed int v8; // edi
HANDLE v9; // eax result = a2;
if ( a2 == 1 )
{
v4 = GetModuleHandleA("ntdll.dll");
dword_407378 = sub_401360(v4, "a7d7bcc95a86a6df3b0a1ccb3c69d440");//此处应该是获取库中的某个函数,我们动态调试的时候看一下
v5 = GetModuleHandleA("ntdll.dll");
dword_407380 = (int (__stdcall *)(_DWORD, _DWORD, _DWORD, _DWORD))sub_401360(v5, "8eb35a28209979fe6a9983cff0d23c5a");
v6 = GetModuleHandleA("kernel32.dll");
dword_407374 = sub_401360(v6, "05577e1568efa10b8166728bfb414c59");
srand(0x61616161u);//设置随机数的种子(影响后面main函数中的rand)
ptr_main = main_401780;//main函数,IDA载入发现已经加密,无法正常解析。
v8 = 440;
do
{
ptr_main = (int (__usercall *)@<eax>(int@<ebp>))((char *)ptr_main + 1);
result = byte_417000[rand() % 8216];
*((_BYTE *)ptr_main - 1) ^= result;//对main进行异或解密
--v8;
}
while ( v8 );
}
else if ( a2 == 3 )
{
v9 = GetCurrentThread();
result = dword_407380(v9, 17, 0, 0);
}
return result;
}
我们动态调试,查看前面要用到库中的哪些函数,并且在main函数解密完成后dump文件,以备后面IDA分析。

发现前面获取的库函数与反调试相关。
重命名后的TLS
char __stdcall TlsCallback_0(int a1, int a2, int a3)
{
char result; // al
HMODULE v4; // eax
HMODULE v5; // eax
HMODULE v6; // eax
int (__usercall *ptr_main)@<eax>(int@<ebp>); // esi
signed int v8; // edi
HANDLE v9; // eax result = a2;
if ( a2 == 1 )
{
v4 = GetModuleHandleA("ntdll.dll");
NtQuerySystemInformation = sub_401360((int)v4, "a7d7bcc95a86a6df3b0a1ccb3c69d440");
v5 = GetModuleHandleA("ntdll.dll");
NtSetInformationThread = (int (__stdcall *)(_DWORD, _DWORD, _DWORD, _DWORD))sub_401360(
(int)v5,
"8eb35a28209979fe6a9983cff0d23c5a");
v6 = GetModuleHandleA("kernel32.dll");
*(_DWORD *)CheckRemoteDebuggerPresent = sub_401360((int)v6, "05577e1568efa10b8166728bfb414c59");
srand(0x61616161u);
ptr_main = main_401780;
v8 = 440;
do
{
ptr_main = (int (__usercall *)@<eax>(int@<ebp>))((char *)ptr_main + 1);
result = byte_417000[rand() % 8216];
*((_BYTE *)ptr_main - 1) ^= result;
--v8;
}
while ( v8 );
}
else if ( a2 == 3 )
{
v9 = GetCurrentThread();
result = NtSetInformationThread(v9, 17, 0, 0);
}
return result;
}
IDA分析mian解密完成时dump的文件
int __usercall sub_401780@<eax>(int a1@<ebp>, int a2@<edi>, int a3@<esi>)
{
signed int v3; // esi
int v4; // ST08_4
int v5; // ST0C_4
int v6; // ST10_4
int v7; // ST14_4
int v8; // ST18_4
int v9; // ST1C_4
int v10; // ST20_4
int v11; // ST24_4
int v12; // ST28_4
int v13; // ST2C_4
int v14; // ecx
const char *v15; // eax
int v17; // [esp-CCh] [ebp-D8h]
int v18; // [esp-C8h] [ebp-D4h]
int v19; // [esp-C4h] [ebp-D0h]
int v20; // [esp-C0h] [ebp-CCh]
int v21; // [esp-BCh] [ebp-C8h]
int v22; // [esp-B8h] [ebp-C4h]
int v23; // [esp-B4h] [ebp-C0h]
int v24; // [esp-B0h] [ebp-BCh]
int v25; // [esp-ACh] [ebp-B8h]
int v26; // [esp-A8h] [ebp-B4h]
int v27; // [esp-A4h] [ebp-B0h]
int v28; // [esp-A0h] [ebp-ACh]
int v29; // [esp-9Ch] [ebp-A8h]
int v30; // [esp-98h] [ebp-A4h]
int v31; // [esp-94h] [ebp-A0h]
int v32; // [esp-90h] [ebp-9Ch]
int v33; // [esp-8Ch] [ebp-98h]
int v34; // [esp-88h] [ebp-94h]
int v35; // [esp-84h] [ebp-90h]
int v36; // [esp-80h] [ebp-8Ch]
int v37; // [esp-7Ch] [ebp-88h]
int v38; // [esp-78h] [ebp-84h]
int v39; // [esp-74h] [ebp-80h]
int v40; // [esp-70h] [ebp-7Ch]
int v41; // [esp-6Ch] [ebp-78h]
int v42; // [esp-68h] [ebp-74h]
int v43; // [esp-64h] [ebp-70h]
int v44; // [esp-60h] [ebp-6Ch]
int v45; // [esp-5Ch] [ebp-68h]
int v46; // [esp-58h] [ebp-64h]
int v47; // [esp-54h] [ebp-60h]
int v48; // [esp-50h] [ebp-5Ch]
int v49; // [esp-4Ch] [ebp-58h]
int v50; // [esp-48h] [ebp-54h]
int v51; // [esp-44h] [ebp-50h]
int v52; // [esp-40h] [ebp-4Ch]
int v53; // [esp-3Ch] [ebp-48h]
int v54; // [esp-38h] [ebp-44h]
int v55; // [esp-34h] [ebp-40h]
__int128 v56; // [esp-30h] [ebp-3Ch]
__int64 v57; // [esp-20h] [ebp-2Ch]
int v58; // [esp-18h] [ebp-24h]
__int16 v59; // [esp-14h] [ebp-20h]
unsigned int v60; // [esp-4h] [ebp-10h]
int v61; // [esp+0h] [ebp-Ch]
int v62; // [esp+4h] [ebp-8h]
int retaddr; // [esp+Ch] [ebp+0h] v61 = a1;
v62 = retaddr;
v60 = (unsigned int)&v61 ^ __security_cookie;
v17 = a3;
CreateThread(0, 0, StartAddress, 0, 0, 0); // 播放歌曲,
printf_401020("%s\n", (unsigned int)aMmmmmmmmmmmmmm);
while ( !song_final_sign_40737C )
{
Sleep(0x7D0u);
printf_401020(">");
}
printf_401020("\n");
v3 = 0;
do
*((_BYTE *)&loc_4015E0 + v3++) ^= byte_417000[rand() % 8216];// main中解密输入的加密处理函数
while ( v3 < 383 );
printf_401020("Shining!\n", a2, v17);
system("cls");
v58 = 0;
v56 = 0i64;
v57 = 0i64;
v59 = 0;
memset(&v38, 0, 0x46u);
printf_401020("My Darling Darling Please!\ninput your key!\n");
scanf_401050("%29s", &v56);
((void (__stdcall *)(__int128 *, int *, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, _DWORD))loc_4015E0)(
&v56,
&v38,
v4,
v5,
v6,
v7,
v8,
v9,
v10,
v11,
v12,
v13,
v18,
v19,
v20,
v21,
v22,
v23,
v24,
v25,
v26,
v27,
v28,
v29,
v30,
v31,
v32,
v33,
v34,
v35,
v36,
v37,
v38,
v39,
v40,
v41,
v42,
v43,
v44,
v45,
v46,
v47,
v48,
v49,
v50,
v51,
v52,
v53,
v54,
v55,
v56);
*(_OWORD *)&v20 = xmmword_403520; // 0DEF0A07232EEBC954C11473ABD57E649
*(_OWORD *)&v24 = xmmword_403530; // 5CCC8CA3C67C5A6A96E49835683F2AC
v36 = 0;
LOWORD(v37) = 0;
*(_OWORD *)&v28 = 0i64;
*(_OWORD *)&v32 = 0i64;
v14 = strcmp((const char *)&v38, (const char *)&v20);
if ( v14 )
v14 = -(v14 < 0) | 1;
v15 = "Maybe next year";
if ( !v14 )
v15 = "Nice Job~";
printf_401020(v15);
system("pause");
return 0;
}
发现main中对loc_4015E0函数进行了解密,后面用他来加密输入。动态调试,解密后dump
loc_4015E0函数
char __cdecl encode_4015E0(const char *myinput, const char *en_temp)
{
int v2; // esi
unsigned int size; // kr00_4
signed int v4; // edi
int v5; // ecx
const char *v6; // eax
int v7; // eax
char v8; // al
int v9; // ecx
int v10; // ecx
unsigned int v11; // ecx
int v12; // eax
char v13; // al
signed int v14; // edi
char result; // al
signed int v16; // esi
char v17; // al
char v18; // cl
signed int v19; // [esp+Ch] [ebp-8h]
signed int v20; // [esp+10h] [ebp-4h] v2 = 0;
size = strlen(myinput);
v4 = 0;
v20 = 4 * size / 3;
if ( v20 > 0 )
{
do
{
v5 = v4 & 3;
if ( v4 & 3 )
{
v8 = myinput[v2 - 1];
if ( v5 == 1 )
{
v9 = myinput[v2++];
v7 = (v9 >> 4) | 16 * (v8 & 3);
}
else if ( v5 == 2 )
{
v10 = myinput[v2++];
v7 = (v10 >> 6) | 4 * (v8 & 0xF);
}
else
{
v7 = v8 & 0x3F;
}
}
else
{
v6 = &myinput[v2++];
v7 = *v6 >> 2;
}
en_temp[v4++] = base64_table_4033C8[v7]; // abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/
}
while ( v4 < v20 );
}
if ( strlen(myinput) % 3 == 1 )
{
v11 = 4 * size / 3;
v12 = 16 * (myinput[v2 - 1] & 3);
*(_WORD *)&en_temp[v20 + 1] = '==';
v13 = base64_table_4033C8[v12]; //魔改base64,编码表将大写字母与小写字母替换了位置。
}
else
{
if ( strlen(myinput) % 3 != 2 )
goto LABEL_15;
v11 = 4 * size / 3;
v13 = base64_table_4033C8[4 * (myinput[v2 - 1] & 0xF)];
en_temp[v20 + 1] = 61;
}
en_temp[v11] = v13;
LABEL_15:
en_temp[strlen(en_temp)] = 0;
v14 = 0;
v19 = strlen(en_temp);
if ( v19 > 0 )
{
do
{
v16 = 6;
do
{
v17 = rand() % 4;
v18 = v16;
v16 -= 2;
result = v17 << v18;
en_temp[v14] ^= result; // 获取伪随机序列,输入进行魔改base64编码后与伪随机序列进行了异或操作。
}
while ( v16 > -2 );
++v14;
}
while ( v14 < v19 );
}
return result;
}
最终main函数
int __usercall sub_401780@<eax>(int a1@<ebp>)
{
signed int v1; // esi
int v2; // ecx
const char *v3; // eax
__int128 tg; // [esp-C0h] [ebp-CCh]
__int128 v6; // [esp-B0h] [ebp-BCh]
__int128 v7; // [esp-A0h] [ebp-ACh]
__int128 v8; // [esp-90h] [ebp-9Ch]
int v9; // [esp-80h] [ebp-8Ch]
__int16 v10; // [esp-7Ch] [ebp-88h]
int temp_str; // [esp-78h] [ebp-84h]
__int128 myinput; // [esp-30h] [ebp-3Ch]
__int64 v13; // [esp-20h] [ebp-2Ch]
int v14; // [esp-18h] [ebp-24h]
__int16 v15; // [esp-14h] [ebp-20h]
unsigned int v16; // [esp-4h] [ebp-10h]
int v17; // [esp+0h] [ebp-Ch]
int v18; // [esp+4h] [ebp-8h]
int retaddr; // [esp+Ch] [ebp+0h] v17 = a1;
v18 = retaddr;
v16 = (unsigned int)&v17 ^ __security_cookie;
printf_401020("%s\n", aMmmmmmmmmmmmmm);
printf_401020("\n");
v1 = 0;
do
*((_BYTE *)encode_4015E0 + v1++) ^= byte_417000[rand() % 8216];
while ( v1 < 383 );
printf_401020("Shining!\n");
system("cls");
v14 = 0;
myinput = 0i64;
v13 = 0i64;
v15 = 0;
memset(&temp_str, 0, 0x46u);
printf_401020("My Darling Darling Please!\ninput your key!\n");
scanf_401050("%29s", &myinput);
encode_4015E0((const char *)&myinput, (const char *)&temp_str);// 魔改base64编码 +异或伪随机序列
tg = xmmword_403520; // 0DEF0A07232EEBC954C11473ABD57E649
v6 = xmmword_403530; // 5CCC8CA3C67C5A6A96E49835683F2AC
v9 = 0;
v10 = 0;
v7 = 0i64;
v8 = 0i64;
v2 = strcmp((const char *)&temp_str, (const char *)&tg);// {
// 0x49, 0xE6, 0x57, 0xBD, 0x3A, 0x47, 0x11, 0x4C, 0x95, 0xBC, 0xEE, 0x32, 0x72, 0xA0, 0xF0, 0xDE,
// 0xAC, 0xF2, 0x83, 0x56, 0x83, 0x49, 0x6E, 0xA9, 0xA6, 0xC5, 0x67, 0x3C, 0xCA, 0xC8, 0xCC, 0x05
// };
if ( v2 )
v2 = -(v2 < 0) | 1;
v3 = "Maybe next year";
if ( !v2 )
v3 = "Nice Job~";
printf_401020(v3);
system("pause");
return nullsub_2((unsigned int)&v17 ^ v16);
}
魔改base64与标准base64编码只存在字母大小写的不同,好解决,关键在于后面与伪随机序列的获取。
方案1、动态调试,在base64编码后,进行异或操作时,编写脚本,将每一位异或数据记录下来。
方案2、先获取魔改base64编码后的结果,然后在函数结束后获得异或加密结果,将二者进行异或,便可得到得到伪随机序列
程序最后将输入的加密结果进行比较,动态调试时dump比较数据。
wp:
import base64
tg=[0x49, 0xE6, 0x57, 0xBD, 0x3A, 0x47, 0x11, 0x4C, 0x95, 0xBC, 0xEE, 0x32, 0x72, 0xA0, 0xF0, 0xDE,
0xAC, 0xF2, 0x83, 0x56, 0x83, 0x49, 0x6E, 0xA9, 0xA6, 0xC5, 0x67, 0x3C, 0xCA, 0xC8, 0xCC, 0x05]
order=[0x08,0x81,0x39,0x8d,0x40,0x09,0x42,0x14,0xd0,0xf2,0x98,0x66,0x33,0xd6,0xc9,0xb2,0xc1,0x95,0xb6,0x1e,0xc7,0x2d,0x1c,0xef,0xd2,0xb2,0x5f,0x66,0x8c,0xb9,0xf1,0x38,0x14,0x08,0x8f,0xce,0xe9,0x7f,0x0d,0x05,] b64=''
for i in range(len(tg)):
b64+=chr(order[i]^tg[i])
print(b64)
t=''
for c in b64:
n=ord(c)
if n>=ord('A') and n<=ord('Z'):
t+=chr(n|0x20)
elif n>=ord('a') and n<=ord('z'):
t+=chr(n&0xdf)
else:
t+=c
print(t)
flag=base64.b64decode(t.encode()).decode()
print(flag)
hctf{1zumi_K0nat4_Mo3}
攻防世界里提交失败 0.0 Orz
LuckyStar hctf2018的更多相关文章
- HCTF2018 pwn题复现
相关文件位置 https://gitee.com/hac425/blog_data/tree/master/hctf2018 the_end 程序功能为,首先 打印出 libc 的地址, 然后可以允许 ...
- off by null 实战
前言 off by null 是一个比较有意思的技术 下面通过 hctf2018 的 heapstrom_zero 实战一波. 相关文件(exp, 题目)位于 https://gitee.com/ha ...
- ASP.NET配置文件里经常使用到的节点信息
web.config文件是一个XML文件,是以<confirguration>为根结点展开的. 上一面从宏观上解说了一下有关配置的文件的内容,以下是一些有关于配置文件经常使用的操作. ...
- 攻防世界 reverse seven
seven hctf2018 这是一个驱动文件 ida载入,查找字符串 根据字符串来到函数:sub_1400012F0 __int64 __fastcall sub_1400012F0(__int6 ...
随机推荐
- how to enable vue cli auto open the localhost url
how to enable vue cli auto open the localhost URL bad you must click the link by manually, waste of ...
- yarn global add !== yarn add global
yarn global add !== yarn add global yarn does not exist the --global flag, but exits yarn global com ...
- Vue Learning Paths
Vue Learning Paths Vue Expert refs https://vueschool.io/articles/vuejs-tutorials/exciting-new-featur ...
- AirPods 2 声音非常小
AirPods 2 声音非常小 bug 停用蓝牙绝对音量 可能是因为开启了耳机的绝对音量功能; 绝对音量功能开启后,耳机的音量和手机音量分开, 可以在手机设置里停用绝对音量; refs http:// ...
- how to change svg polygon size by update it's points in js
how to change svg polygon size by update it's points in js matrixTransform https://stackoverflow.com ...
- ts 索引签名 无视多余的属性类型
interface SquareConfig { color?: string; width?: number; [propName: string]: any; } function asd(opt ...
- 苏黎世财经对话区块链专家,NGK如何利用时间价值实现自身的垂直扩张?
近日,苏黎世财经日报联合法兰西金融等多家知名媒体,专访了NGK. 苏黎世财经日报专栏记者玛科尔德表示,随着NGK DeFi的明星代币BGV登上去中心化金融的舞台,它千倍的收益率让生态投资者趋之若鹜. ...
- Masterboxan INC 下半年将聚焦超高净值和家族全权委托客户
"投资是一个没有终点的奋斗.我们不能简单的预测市场,而是应对市场做出正确的反应.这需要我们不断反思.总结.提升,找到自己的投资哲学,然后用一生的时间去坚守."Masterboxan ...
- 【commons-pool2源码】写前思考
写作的初衷 工作4年多, 一直没有系统的阅读过优秀的开源代码, 所以从今年开始做一些尝试, 阅读源码并且试着将自己的理解以文章的形式输出, 从而达到以下目的: 通过阅读源码提升自身的技术水准, 通过写 ...
- Django Admin 图片路径设置显示为图片(imageField显示方法设置)
一 使用环境 开发系统: windows IDE: pycharm 数据库: msyql,navicat 编程语言: python3.7 (Windows x86-64 executable in ...