ps:学习了一下大家写文章的方式,以后就都这么写了,之前的第一篇就懒得改了,参考了网上师傅的wp
题目链接:5a6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1N6i4g2G2K9W2)9J5k6h3y4F1i4K6u0r3j5$3S2S2L8r3I4W2L8X3N6W2M7#2)9J5x3$3y4J5j5h3y4C8e0h3f1`.

通过题目内容可以了解到,用户名是welcomebeijing,密码MD5的小写哈希就是我们的flag。点开程序,可以看到关键字符串,大致的思路就是通过这个字符串可以定位到关键函数,再进行进一步分析。
先用查壳软件看一下程序情况

是一个无壳的32位PE文件,用IDA32打开,定位到主函数
对于一些不是很重要的函数的作用我都直接在上面的函数注明了,比较重要的,我会在下文着重分析。
这个函数就是对user进行了一系列操作,最后把值赋给了byte_416050这个数组,我看着很像RC4加密,后面可以直接动调出来
一下子就能看见有好几个反调试的语句,第一个while循环里的意思就是将输入的密码,例如123456,按0x12,0x34,0x56这样两位切割,然后放在v14数组里面。接下来重点就是第二个循环,我们先来看这个sub_401710函数
在上面这个函数中 v4是user用户名的长度,a3是两位一组后的密码分组个数计数,v4是永远大于a3的。else if里面的操作就是把V6和用户名异或再把值存放在v16里,为了区别,这里将新的v16记作v16'。然后就是sub_401470,我们通过return语句可以推出,v13 == 0xAB94,通过这个我们就可以推出v16'的值。
这里面的a2就是v16',只要v16'的每一位值能等于这里面if判断语句的每一个值就会输出v13 == 0xAB94,所以v16'=dbappfsec。然后我们就可以通过v16'和用户名异或得出v16,再把v16和byte_416050数组异或就可以得出我们要的两位一组分割后的密码,最后拼起来就行。现在我们唯一缺的就是byte_416050数组,这里可以通过动态调试得出
动态调试之前需要先将前面的反调试语句处理一下,将下图处的jz改为jmp就行了

然后我们再去看一下关键位置的汇编代码


可以看见我们只需要观察ecx的值就可以得出byte_416050数组的值,动调得出值为0x2A, 0xD7, 0x92, 0xE9, 0x53, 0xE2, 0xC4, 0xCD。ps:这里动调的值,不知道是程序原因还是什么原因,动调出来的值跟网上动调出来的值不一样,最后搬的网上师傅动调出来的值,有师傅知道的可以在评论区指点一手。
奇怪的是这个结果程序是可以通过的,但是提交到Buuctf没通过,网上的一些wp的结果提交到Buuctf是可以的,但是通不过程序的检验,不知道是不是Buuctf的flag错了。网上其他wp的结果是4eb5f3992391a1ae,大家可以自己试一下。

int wmain()
{
FILE *v0; // eax
FILE *v1; // eax
char v3; // [esp+3h] [ebp-405h]
char v4; // [esp+4h] [ebp-404h] BYREF
char v5[255]; // [esp+5h] [ebp-403h] BYREF
char Format; // [esp+104h] [ebp-304h] BYREF
char v7[255]; // [esp+105h] [ebp-303h] BYREF
char v8; // [esp+204h] [ebp-204h] BYREF
char v9[255]; // [esp+205h] [ebp-203h] BYREF
char v10; // [esp+304h] [ebp-104h] BYREF
char v11[255]; // [esp+305h] [ebp-103h] BYREF
printf("Come one! Crack Me~~~\n");
v10 = 0;
memset(v11, 0, sizeof(v11));
v8 = 0;
memset(v9, 0, sizeof(v9));
while ( 1 )
{
do
{
do
{
printf("user(6-16 letters or numbers):");
scanf("%s", &v10);
v0 = (FILE *)sub_4024BE();
fflush(v0);
}
while ( !(unsigned __int8)sub_401000(&v10) );
printf("password(6-16 letters or numbers):");
scanf("%s", &v8);
v1 = (FILE *)sub_4024BE();
fflush(v1);
}
while ( !(unsigned __int8)sub_401000(&v8) );
sub_401090(&v10);
Format = 0;
memset(v7, 0, sizeof(v7));
v4 = 0;
memset(v5, 0, sizeof(v5));
v3 = ((int (__cdecl *)(char *, char *))loc_4011A0)(&Format, &v4);
if ( (unsigned __int8)sub_401830(&v10, &v8) )
{
if ( v3 )
break;
}
printf(&v4);
}
printf(&Format);
return 0;
}
int wmain()
{
FILE *v0; // eax
FILE *v1; // eax
char v3; // [esp+3h] [ebp-405h]
char v4; // [esp+4h] [ebp-404h] BYREF
char v5[255]; // [esp+5h] [ebp-403h] BYREF
char Format; // [esp+104h] [ebp-304h] BYREF
char v7[255]; // [esp+105h] [ebp-303h] BYREF
char v8; // [esp+204h] [ebp-204h] BYREF
char v9[255]; // [esp+205h] [ebp-203h] BYREF
char v10; // [esp+304h] [ebp-104h] BYREF
char v11[255]; // [esp+305h] [ebp-103h] BYREF
printf("Come one! Crack Me~~~\n");
v10 = 0;
memset(v11, 0, sizeof(v11));
v8 = 0;
memset(v9, 0, sizeof(v9));
while ( 1 )
{
do
{
do
{
printf("user(6-16 letters or numbers):");
scanf("%s", &v10);
v0 = (FILE *)sub_4024BE();
fflush(v0);
}
while ( !(unsigned __int8)sub_401000(&v10) );
printf("password(6-16 letters or numbers):");
scanf("%s", &v8);
v1 = (FILE *)sub_4024BE();
fflush(v1);
}
while ( !(unsigned __int8)sub_401000(&v8) );
sub_401090(&v10);
Format = 0;
memset(v7, 0, sizeof(v7));
v4 = 0;
memset(v5, 0, sizeof(v5));
v3 = ((int (__cdecl *)(char *, char *))loc_4011A0)(&Format, &v4);
if ( (unsigned __int8)sub_401830(&v10, &v8) )
{
if ( v3 )
break;
}
printf(&v4);
}
printf(&Format);
return 0;
}
_BYTE *__cdecl sub_401090(_BYTE *a1)
{
_BYTE *result; // eax
int v2; // [esp+Ch] [ebp-18h]
int v3; // [esp+10h] [ebp-14h]
_BYTE *v4; // [esp+14h] [ebp-10h]
int i; // [esp+18h] [ebp-Ch]
char v7; // [esp+20h] [ebp-4h]
char v8; // [esp+22h] [ebp-2h]
unsigned __int8 v9; // [esp+23h] [ebp-1h]
for ( i = 0; i < 256; ++i )
byte_416050[i] = i;
v2 = 0;
v9 = 0;
v3 = 0;
result = a1;
v4 = a1;
do
LOBYTE(result) = *v4;
while ( *v4++ );
while ( v2 < 256 )
{
v8 = byte_416050[v2];
v9 += v8 + a1[v3];
v7 = byte_416050[v9];
++v3;
byte_416050[v9] = v8;
byte_416050[v2] = v7;
result = (_BYTE *)v3;
if ( v3 >= v4 - (a1 + 1) )
v3 = 0;
++v2;
}
return result;
}
_BYTE *__cdecl sub_401090(_BYTE *a1)
{
_BYTE *result; // eax
int v2; // [esp+Ch] [ebp-18h]
int v3; // [esp+10h] [ebp-14h]
_BYTE *v4; // [esp+14h] [ebp-10h]
int i; // [esp+18h] [ebp-Ch]
char v7; // [esp+20h] [ebp-4h]
char v8; // [esp+22h] [ebp-2h]
unsigned __int8 v9; // [esp+23h] [ebp-1h]
for ( i = 0; i < 256; ++i )
byte_416050[i] = i;
v2 = 0;
v9 = 0;
v3 = 0;
result = a1;
v4 = a1;
do
LOBYTE(result) = *v4;
while ( *v4++ );
while ( v2 < 256 )
{
v8 = byte_416050[v2];
v9 += v8 + a1[v3];
v7 = byte_416050[v9];
++v3;
byte_416050[v9] = v8;
byte_416050[v2] = v7;
result = (_BYTE *)v3;
if ( v3 >= v4 - (a1 + 1) )
v3 = 0;
++v2;
}
return result;
}
bool __cdecl sub_401830(int a1, const char *a2)
{
int v3; // [esp+18h] [ebp-22Ch]
int v4; // [esp+1Ch] [ebp-228h]
int v5; // [esp+28h] [ebp-21Ch]
unsigned int v6; // [esp+30h] [ebp-214h]
char v7; // [esp+36h] [ebp-20Eh]
char v8; // [esp+37h] [ebp-20Dh]
char v9; // [esp+38h] [ebp-20Ch]
unsigned __int8 v10; // [esp+39h] [ebp-20Bh]
unsigned __int8 v11; // [esp+3Ah] [ebp-20Ah]
char v12; // [esp+3Bh] [ebp-209h]
int v13; // [esp+3Ch] [ebp-208h] BYREF
char v14; // [esp+40h] [ebp-204h] BYREF
char v15[255]; // [esp+41h] [ebp-203h] BYREF
char v16; // [esp+140h] [ebp-104h] BYREF
char v17[255]; // [esp+141h] [ebp-103h] BYREF
v4 = 0;
v5 = 0;
v11 = 0;
v10 = 0;
v16 = 0;
memset(v17, 0, sizeof(v17));
v14 = 0;
memset(v15, 0, sizeof(v15));
v9 = 0;
v6 = 0;
v3 = 0;
while ( v6 < strlen(a2) )
{
if ( isdigit(a2[v6]) )
{
v8 = a2[v6] - 48;
}
else if ( isxdigit(a2[v6]) )
{
if ( *((_DWORD *)NtCurrentPeb()->SubSystemData + 3) != 2 )
a2[v6] = 34;
v8 = (a2[v6] | 0x20) - 87;
}
else
{
v8 = ((a2[v6] | 0x20) - 97) % 6 + 10;
}
__rdtsc();
__rdtsc();
v9 = v8 + 16 * v9;
if ( !((int)(v6 + 1) % 2) )
{
*(&v14 + v3++) = v9;
v9 = 0;
}
++v6;
}
while ( v5 < 8 )
{
v10 += byte_416050[++v11];
v12 = byte_416050[v11];
v7 = byte_416050[v10];
byte_416050[v10] = v12;
byte_416050[v11] = v7;
if ( ((int)NtCurrentPeb()->UnicodeCaseTableData & 0x70) != 0 )
v12 = v10 + v11;
*(&v16 + v5) = byte_416050[(unsigned __int8)(v7 + v12)] ^ *(&v14 + v4);
if ( (unsigned __int8)*(_DWORD *)&NtCurrentPeb()->BeingDebugged )
{
v10 = -83;
v11 = 43;
}
sub_401710(&v16, a1, v5++);
v4 = v5;
if ( v5 >= (unsigned int)(&v14 + strlen(&v14) + 1 - v15) )
v4 = 0;
}
v13 = 0;
sub_401470(&v16, &v13);
return v13 == 0xAB94;
}
bool __cdecl sub_401830(int a1, const char *a2)
{
int v3; // [esp+18h] [ebp-22Ch]
int v4; // [esp+1Ch] [ebp-228h]
int v5; // [esp+28h] [ebp-21Ch]
unsigned int v6; // [esp+30h] [ebp-214h]
char v7; // [esp+36h] [ebp-20Eh]
char v8; // [esp+37h] [ebp-20Dh]
char v9; // [esp+38h] [ebp-20Ch]
unsigned __int8 v10; // [esp+39h] [ebp-20Bh]
unsigned __int8 v11; // [esp+3Ah] [ebp-20Ah]
char v12; // [esp+3Bh] [ebp-209h]
int v13; // [esp+3Ch] [ebp-208h] BYREF
char v14; // [esp+40h] [ebp-204h] BYREF
char v15[255]; // [esp+41h] [ebp-203h] BYREF
char v16; // [esp+140h] [ebp-104h] BYREF
char v17[255]; // [esp+141h] [ebp-103h] BYREF
v4 = 0;
v5 = 0;
v11 = 0;
v10 = 0;
v16 = 0;
memset(v17, 0, sizeof(v17));
v14 = 0;
memset(v15, 0, sizeof(v15));
v9 = 0;
v6 = 0;
v3 = 0;
while ( v6 < strlen(a2) )
{
if ( isdigit(a2[v6]) )
{
v8 = a2[v6] - 48;
}
else if ( isxdigit(a2[v6]) )
{
if ( *((_DWORD *)NtCurrentPeb()->SubSystemData + 3) != 2 )
a2[v6] = 34;
v8 = (a2[v6] | 0x20) - 87;
}
else
{
v8 = ((a2[v6] | 0x20) - 97) % 6 + 10;
}
__rdtsc();
__rdtsc();
[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!