本题防守方采用了多层VM的设计思路,比赛中VM常见,多层VM罕见,让攻击者欲罢不能。
当攻击者们在寻找快速方案如手解等方式拨开第一层VM后,发现后面还是VM,套娃感凸现,一望无际,定力稍有不慎,可能就会被吓住。这时候需要攻击者使用各种看家本领透视VM业务逻辑,层层击破,得到可阅读的代码。
当VM面纱都揭开时,高层VM对底层VM的运行时修改以及暗藏逻辑的触发联动机制也需要一一解开,才能联合起来得到完整的验证逻辑进行解题。高层VM对支撑其运作的低层VM修改和联动,除了套娃感,也略带虚拟逃逸感。总体设计非常优秀,相信各位攻击者都有所得。
设计思路由作者 ccfer 提供
LightsOut求解直接用sage也是迅速得出结果。
crc暴力穷举会慢点,不过4字节得相当于可逆,有快速破解方法。
设计思路由作者 k1ee 提供
struct vm_sub
{
int param1; //6, 6, 6, 3
int param2; //ins1, ins2, ins3, input_hex
char* vm_ins;
int size;
int idk_0;
int id;
int idk7;
int idk8;
};
struct vm_fin
{
unsigned char* input_hex;
int* len_buf;
vm_sub* vmsub;
};
struct vm_context
{
vm_sub subs[4];
vm_fin fin;
};
...
void disassembly_vm1(vm_sub* ctx)
{
char* eip = ctx->vm_ins;
char* esp = eip + 2 * ctx->size;
ks_engine* ks;
ks_err err;
err = ks_open(KS_ARCH_X86, KS_MODE_32, &ks);
if (err != KS_ERR_OK)
{
cout << "Keystone open error." << endl;
return;
}
ostringstream dasm = ostringstream();
dasm << "push 6;" << endl;
dasm << "push 0x20000;" << endl;
dasm << "call vmins_0;" << endl;
dasm << "jmp vmins_ret;" << endl;
while (eip < ctx->vm_ins + 0x792)
{
int vm_offset = eip - ctx->vm_ins;
dasm << "vmins_" << vm_offset << ":" << endl;
int ins = *eip++;
switch (ins)
{
case 17:
{
dasm << "push ebx;" << endl;
break;
}
......
完整源码在此处查看:
https://bbs.pediy.com/thread-263829.htm


int vm3_memcpy(char* dst, char* src, int len)
{
vm_fin* v18 = &ctx.fin;
unsigned char * v17 = v18->input_hex;
int* v16 = new int[10];
v16[2] = 0xDEC0CCAE;
*(v16 + 2) = crc32(0xFFFFFFFF, v16 + 2);
*(v16 + 2) = crc32(0xFFFFFFFF, v16 + 2);
*(v16 + 2) = crc32(0xFFFFFFFF, v16 + 2);
*(v16 + 2) = crc32(0xFFFFFFFF, v16 + 2);
*(v16 + 2) = crc32(0xFFFFFFFF, v16 + 2);
*(v16 + 2) = crc32(0xFFFFFFFF, v16 + 2);
*(v16 + 2) = crc32(0xFFFFFFFF, v16 + 2);
*(v16 + 2) = crc32(0xFFFFFFFF, v16 + 2);
if (*(v16 + 2) == 0xDE05629C)
return 1;
return 0;
}
result = d54b1112 target = de05629c
result = 5ba49ea3 target = d54b1112
result = f16f3846 target = 5ba49ea3
result = 84b4f299 target = f16f3846
result = 3731ce56 target = 84b4f299
result = 74f3e321 target = 3731ce56
result = 20558f1 target = 74f3e321
result = dec0ccae target = 20558f1
result = f812fce7 target = dec0ccae
int vm3_memset_1(char* dst, char val, int len)
{
vm_fin* v18 = &ctx.fin;
char* hex = (char *)v18->input_hex;
int* v16 = v18->len_buf;
int* v6 = v16 + 4;
*v6 = sub_E21(hex); // equals D540
v6 = v16 + 2;
*v6 = sub_109A(hex + 4, (char*)v16 + 256);
memset(v16 + 1024, 1, 100);
sub_1517((char*)v16 + 256, (char*)v16 + 4096);
return 0;
}
unsigned int __cdecl sub_109A(char* a1, char* a2)
{
int v3; // [esp+3ECh] [ebp-14h]
char* v4; // [esp+3F0h] [ebp-10h]
unsigned __int8 v5; // [esp+3F4h] [ebp-Ch]
unsigned int v6; // [esp+3F8h] [ebp-8h]
unsigned int v7; // [esp+3FCh] [ebp-4h]
v4 = a2;
v7 = 0;
v3 = 0;
while (v7 < 15)
{
v6 = 0;
v5 = a1[v7];
v3 <<= 1;
v3 |= (unsigned int)v5 >> 7;
while (v6 < 7)
{
*v4 = v5 & 1;
v5 >>= 1;
++v4;
++v6;
}
++v7;
}
return (((v3 << 8) + ((unsigned int)(unsigned __int8)a1[14] >> 2)) << 8) + (unsigned __int8)a1[15];
}
AE CC C0 DE 0C 32 56 F7 5E 37 A6 BF A2 27 A2 ED 3D 54 AC 96 4B 43 54 46 32 30 32 30 46 6C 61 67
int vm3_memset_2(char* dst, char val, int len)
{
vm_fin* v18 = &ctx.fin;
char* v17 = (char *)v18->input_hex;
int* v16 = v18->len_buf;
int* v6 = v16 + 2;
*v6 = sub_179A(v17 + 32, (char *)v16 + 64*4);
if (*v6 == 2)
{
memset(v16 + 1024, 1, 1600);
sub_2FB9((char*)v16 + 4*64, (char*)v16 + 4*1024);
}
return 0;
}
uint32_t limit = pow(2, 20) - 1;
for (uint32_t val = 0; val <= limit; ++val)
{
for (int i = 0; i < 20; ++i)
{
uint8_t bit = (val >> i) & 0b1;
mat[0][i] = bit;
mat[0][39 - i] = bit;
}
memset(table, 1, sizeof(table));
for (int i = 0; i < 40; ++i)
{
for (int k = 0; k < 40; ++k)
{
uint8_t bit = mat[i][k];
table[i][k] ^= bit;
if (i > 0)
table[i - 1][k] ^= bit;
if (i < 39)
table[i + 1][k] ^= bit;
if (k > 0)
table[i][k - 1] ^= bit;
if (k < 39)
table[i][k + 1] ^= bit;
}
if (i != 39)
{
for (int k = 0; k < 40; ++k)
{
mat[i + 1][k] = table[i][k];
}
}
}
if (memcmp(table, truth, sizeof(truth)) == 0)
{
printf("Resultn");
printf("arr = []n");
for (int i = 0; i < 40; ++i)
{
printf("arr.append([");
for (int k = 0; k < 40; ++k)
{
printf("%d%s", mat[i][k], k == 39 ? "" : ", ");
}
printf("]n");
}
}
}
看完解析你会了吗?你还有不一样的解题思路吗? 实践出真知~速速动手自己做一遍,才算把知识装进脑子~ 欢迎大家分享解题思路哦~
现在第六题《兵刃相向》正在火热进行中!
有你比赛更精彩!
越早提交答案,得分越高哦!
立即扫码加入战斗!
赛题回顾
出题战队:七星战队
出题战队:中娅之戒
出题战队:2019
出题战队:大灰狼爱喜羊羊
你的好友秀秀子拍了拍你
并请你点击阅读原文,参与最新一题的挑战!
本文始发于微信公众号(看雪学院):2020 KCTF秋季赛 | 第五题设计思路及解题思路
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论