Ha1cyon_CTF-公开赛(wp)
一.babyasm
00007FF7A8AC5A50 push rbp
00007FF7A8AC5A52 push rdi
00007FF7A8AC5A53 sub rsp,238h
00007FF7A8AC5A5A lea rbp,[rsp+20h]
00007FF7A8AC5A5F mov rdi,rsp
00007FF7A8AC5A62 mov ecx,8Eh
00007FF7A8AC5A67 mov eax,0CCCCCCCCh
00007FF7A8AC5A6C rep stos dword ptr [rdi]
00007FF7A8AC5A6E mov rax,qword ptr [__security_cookie (07FF7A8AD3018h)]
00007FF7A8AC5A75 xor rax,rbp
00007FF7A8AC5A78 mov qword ptr [rbp+208h],rax
00007FF7A8AC5A7F lea rcx,[__06A15900_ConsoleApplication@cpp (07FF7A8AD902Ah)]
00007FF7A8AC5A86 call __CheckForDebuggerJustMyCode (07FF7A8AC1122h)
00007FF7A8AC5A8B lea rdx,[string "flag{this_is_a_fake_flag}" (07FF7A8ACF450h)]
00007FF7A8AC5A92 lea rcx,[flag]
00007FF7A8AC5A96 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (07FF7A8AC15E1h)
00007FF7A8AC5A9B nop
00007FF7A8AC5A9C mov dword ptr [p],0
00007FF7A8AC5AA3 mov dword ptr [rbp+64h],0
00007FF7A8AC5AAA jmp main+64h (07FF7A8AC5AB4h)
00007FF7A8AC5AAC mov eax,dword ptr [rbp+64h]
00007FF7A8AC5AAF inc eax
00007FF7A8AC5AB1 mov dword ptr [rbp+64h],eax
00007FF7A8AC5AB4 movsxd rax,dword ptr [rbp+64h]
00007FF7A8AC5AB8 mov qword ptr [rbp+1F8h],rax
00007FF7A8AC5ABF lea rcx,[flag]
00007FF7A8AC5AC3 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::length (07FF7A8AC122Bh)
00007FF7A8AC5AC8 mov rcx,qword ptr [rbp+1F8h]
00007FF7A8AC5ACF cmp rcx,rax
00007FF7A8AC5AD2 jae main+1B2h (07FF7A8AC5C02h)
00007FF7A8AC5AD8 mov eax,dword ptr [rbp+64h]
00007FF7A8AC5ADB and eax,1
00007FF7A8AC5ADE cmp eax,1
00007FF7A8AC5AE1 jne main+126h (07FF7A8AC5B76h)
00007FF7A8AC5AE7 movsxd rax,dword ptr [rbp+64h]
00007FF7A8AC5AEB mov rdx,rax
00007FF7A8AC5AEE lea rcx,[flag]
00007FF7A8AC5AF2 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator[] (07FF7A8AC1442h)
00007FF7A8AC5AF7 movsx eax,byte ptr [rax]
00007FF7A8AC5AFA xor eax,42h
00007FF7A8AC5AFD mov dword ptr [p],eax
00007FF7A8AC5B00 mov dl,30h
00007FF7A8AC5B02 lea rcx,[rbp+144h]
00007FF7A8AC5B09 call std::setfill<char> (07FF7A8AC1046h)
00007FF7A8AC5B0E mov qword ptr [rbp+1F8h],rax
00007FF7A8AC5B15 mov edx,2
00007FF7A8AC5B1A lea rcx,[rbp+168h]
00007FF7A8AC5B21 call std::setw (07FF7A8AC10D2h)
00007FF7A8AC5B26 mov qword ptr [rbp+200h],rax
00007FF7A8AC5B2D lea rdx,[std::hex (07FF7A8AC1488h)]
00007FF7A8AC5B34 mov rcx,qword ptr [__imp_std::cout (07FF7A8AD71C0h)]
00007FF7A8AC5B3B call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7160h)]
00007FF7A8AC5B41 mov rcx,qword ptr [rbp+200h]
00007FF7A8AC5B48 mov rdx,rcx
00007FF7A8AC5B4B mov rcx,rax
00007FF7A8AC5B4E call std::operator<<<char,std::char_traits<char>,__int64> (07FF7A8AC12F8h)
00007FF7A8AC5B53 mov rcx,qword ptr [rbp+1F8h]
00007FF7A8AC5B5A mov rdx,rcx
00007FF7A8AC5B5D mov rcx,rax
00007FF7A8AC5B60 call std::operator<<<char,std::char_traits<char>,char> (07FF7A8AC11A4h)
00007FF7A8AC5B65 mov edx,dword ptr [p]
00007FF7A8AC5B68 mov rcx,rax
00007FF7A8AC5B6B call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7158h)]
00007FF7A8AC5B71 jmp main+1ADh (07FF7A8AC5BFDh)
00007FF7A8AC5B76 movsxd rax,dword ptr [rbp+64h]
00007FF7A8AC5B7A mov rdx,rax
00007FF7A8AC5B7D lea rcx,[flag]
00007FF7A8AC5B81 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator[] (07FF7A8AC1442h)
00007FF7A8AC5B86 movsx eax,byte ptr [rax]
00007FF7A8AC5B89 mov dword ptr [p],eax
00007FF7A8AC5B8C mov dl,30h
00007FF7A8AC5B8E lea rcx,[rbp+194h]
00007FF7A8AC5B95 call std::setfill<char> (07FF7A8AC1046h)
00007FF7A8AC5B9A mov qword ptr [rbp+1F8h],rax
00007FF7A8AC5BA1 mov edx,2
00007FF7A8AC5BA6 lea rcx,[rbp+1B8h]
00007FF7A8AC5BAD call std::setw (07FF7A8AC10D2h)
00007FF7A8AC5BB2 mov qword ptr [rbp+200h],rax
00007FF7A8AC5BB9 lea rdx,[std::hex (07FF7A8AC1488h)]
00007FF7A8AC5BC0 mov rcx,qword ptr [__imp_std::cout (07FF7A8AD71C0h)]
00007FF7A8AC5BC7 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7160h)]
00007FF7A8AC5BCD mov rcx,qword ptr [rbp+200h]
00007FF7A8AC5BD4 mov rdx,rcx
00007FF7A8AC5BD7 mov rcx,rax
00007FF7A8AC5BDA call std::operator<<<char,std::char_traits<char>,__int64> (07FF7A8AC12F8h)
00007FF7A8AC5BDF mov rcx,qword ptr [rbp+1F8h]
00007FF7A8AC5BE6 mov rdx,rcx
00007FF7A8AC5BE9 mov rcx,rax
00007FF7A8AC5BEC call std::operator<<<char,std::char_traits<char>,char> (07FF7A8AC11A4h)
00007FF7A8AC5BF1 mov edx,dword ptr [p]
00007FF7A8AC5BF4 mov rcx,rax
00007FF7A8AC5BF7 call qword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (07FF7A8AD7158h)]
00007FF7A8AC5BFD jmp main+5Ch (07FF7A8AC5AACh)
00007FF7A8AC5C02 mov dword ptr [rbp+1E4h],0
00007FF7A8AC5C0C lea rcx,[flag]
00007FF7A8AC5C10 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> > (07FF7A8AC1302h)
00007FF7A8AC5C15 mov eax,dword ptr [rbp+1E4h]
00007FF7A8AC5C1B mov edi,eax
00007FF7A8AC5C1D lea rcx,[rbp-20h]
00007FF7A8AC5C21 lea rdx,[__xt_z+540h (07FF7A8ACEFE0h)]
00007FF7A8AC5C28 call _RTC_CheckStackVars (07FF7A8AC1596h)
00007FF7A8AC5C2D mov eax,edi
00007FF7A8AC5C2F mov rcx,qword ptr [rbp+208h]
00007FF7A8AC5C36 xor rcx,rbp
00007FF7A8AC5C39 call __security_check_cookie (07FF7A8AC1190h)
00007FF7A8AC5C3E lea rsp,[rbp+218h]
00007FF7A8AC5C45 pop rdi
00007FF7A8AC5C46 pop rbp
00007FF7A8AC5C47 ret
很无语,很多花指令没啥用的,给了个txt文件,应该是个加密过的,然后又给了asm文件,应该是个encoder,仔细看了看唯一动了flag的地方就是那个xor,额外关注一下,然后把加密后的转换成字符串,发现隔一个就会乱码,说明是突破点,同时发现验证后,就是偶数的时候异或,奇数不异或,写个脚本,过了
#301d7972751d6b2c6f355f3a38742d74341d61776d7d7d
str="662e61257b26301d7972751d6b2c6f355f3a38742d74341d61776d7d7d"
flag=""
w=0
for i in range(0,len(str),2):
tmp=""
tmp+=str[i]
tmp+=str[i+1]
if w%2==0:
flag+=chr(int(tmp,16))
else:
a=int(tmp,16)^0x42
flag+=chr(a)
w+=1
# a=0x30^0x42
# print(chr(a))
print(flag)
二.Baby obfuscation
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // eax
int v4; // ebx
int v5; // esi
int v6; // ebx
int v7; // ebx
int v8; // esi
int v9; // edi
int v10; // ebx
int v11; // ebx
int v12; // ebx
int v13; // esi
int v14; // eax
int v15; // ebx
int v16; // esi
int v17; // ebx
int v18; // eax
bool v19; // bl
int v20; // eax
int v21; // esi
int v22; // ebx
int v23; // ebx
int v24; // eax
int v25; // eax
int v26; // eax
int v27; // eax
int v28; // ebx
int a[64]; // [rsp+20h] [rbp-60h]
int v31; // [rsp+120h] [rbp+A0h]
char Str[1008]; // [rsp+130h] [rbp+B0h]
int v33[1000]; // [rsp+520h] [rbp+4A0h]
int v34; // [rsp+14C0h] [rbp+1440h]
int v35; // [rsp+14D0h] [rbp+1450h]
int v36; // [rsp+14D4h] [rbp+1454h]
int v37; // [rsp+14D8h] [rbp+1458h]
int v38; // [rsp+14DCh] [rbp+145Ch]
int v39; // [rsp+14E0h] [rbp+1460h]
int v40; // [rsp+14E4h] [rbp+1464h]
int v41; // [rsp+14E8h] [rbp+1468h]
int v42; // [rsp+14ECh] [rbp+146Ch]
int v43; // [rsp+14F0h] [rbp+1470h]
int k; // [rsp+14F4h] [rbp+1474h]
int j; // [rsp+14F8h] [rbp+1478h]
int i; // [rsp+14FCh] [rbp+147Ch]
_main();
memset(v33, 0, sizeof(v33));
v34 = 0;
memset(a, 0, sizeof(a));
v31 = 0;
for ( i = 0; i <= 64; ++i )
a[i] = i + 1;
v39 = 2;
v40 = 3;
v41 = 4;
v42 = 5;
v35 = 2;
v36 = 3;
v37 = 4;
v38 = 5;
puts("WHERE IS MY KEY!?");
scanf("%32s", Str);
v43 = strlen(Str); // 字符串长度
v3 = F0X1(a[j], a[j]); // F0x1为求最大公约数
for ( j = v3 / a[j]; j <= v43; ++j )
{
v4 = (a[j] + a[j + 1]) * (a[j] + a[j + 1]);
if ( v4 >= F0X5(2, 2) * a[j] * a[j + 1] ) // 看位数里有多少个1
{
v5 = ~Str[F0X4(j, 1)]; // 减一
v6 = F0X4(j, 1);
v33[j] = ~(v5 + *(&v39 + v6 % F0X5(2, 2)));// F0x5是2的几次方
}
v7 = F0X1(a[j], a[j + 1]);
if ( v7 > F0X1(a[j + 1], ~(~a[j + 1] + a[j])) )// 无视
{
v8 = v33[j];
v9 = ~v33[j];
v10 = F0X4(j, 1);
v33[j] = ~(v9 + a[v10 % F0X5(2, 2)]) * v8;
}
v11 = a[j + 1];
v12 = F0X5(2, 1) * v11;
v13 = a[j];
v14 = F0X5(2, 1);
v15 = F0X1(v13 * v14, v12); // 2*a[j],2*a[j+1]
v16 = F0X5(2, 1);
if ( v15 == v16 * F0X1(a[j], a[j + 1]) )
{
v17 = F0X4(j, 1);
v33[j] ^= *(&v39 + v17 % F0X5(2, 2));
}
v18 = F0X5(V0X3, a[j]); // 3的a[j]次方
v19 = v18 < a[j] + 1; // false
v20 = F0X5(2, 4);
if ( F0X3(v20 >= j, v19) ) // 无视
{
v21 = ~Str[F0X4(j, 1)];
v22 = F0X4(j, 1);
v33[j] ^= ~(v21 + *(&v39 + v22 % F0X5(2, 2)));
}
v23 = F0X5(2, 3);
v24 = F0X1(a[j], a[j]);
v33[j] *= v23 + F0X5(2, v24 / a[j]);
}
v25 = F0X5(2, 4);
v26 = F0X4(v25, 1);
if ( v26 == v43 )
{
v27 = F0X1(a[k], a[k]);
for ( k = v27 / a[k]; k <= v43; ++k )
{
v28 = v33[k];
if ( v28 == F0X4(A0X6[k], 1) / 10 )
++V0X2;
}
if ( V0X2 == v43 )
puts("\nPASS");
else
puts("\nDENIED");
}
else
{
puts("\nDENIED");
}
return 0;
}
- 还是挺恶心人的,这么多逻辑运算,看上去挺吓人的,实际上,分析起来,发现挺简单的。。。
- ~ (~ a+b)这玩意的意思就是减法。。。花里胡哨。。
final=[0x0,0x1E79,0x1E79,0x2135,0x170D,0x1F41,0x1901,0x2CED,0x11F9,0x2649,0x2581,0x2DB5,0x14B5,0x25E5,0x2A31,0x30D5]
v33=[]
v39=[2,3,4,5]
v33.append(0)
for i in range(1,16):
v33.append((final[i]-1)/10)
flag=""
for w in range(1,16):
v33[w]/=10
v33[w]=int(v33[w])
v33[w]^=v39[(w-1)%4]
v5=(~v33[w])-v39[(w-1)%4]
flag+=chr(~v5&0xff)
print(flag)
第三题:
逻辑还是很清晰的,结果我用手逆了。。。。。。心态炸了。。。昂哥说要学会暴算,讲道理要听,
魔改了base64可还行,基本可以看出是4个字符,换成了三个字符,base64应该是3个ASCII字符,变成了4个字符。。。。直接爆破吧,手逆有点不现实,但是应该也能写出来,等wp吧,顺便学习一下
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
__int64 __fastcall find_pos(char a1)
{
return strrchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234{}789+/=", a1)
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234{}789+/=";
}
char table[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234{}789+/=";
void *__fastcall RxEncode(const char *Str, int len)
{
void *result; // rax
int v3; // [rsp+18h] [rbp-38h]
signed int v4; // [rsp+1Ch] [rbp-34h]
int v5; // [rsp+20h] [rbp-30h]
signed int v6; // [rsp+24h] [rbp-2Ch]
int v7; // [rsp+28h] [rbp-28h]
int v8; // [rsp+28h] [rbp-28h]
signed int i; // [rsp+2Ch] [rbp-24h]
unsigned char *v10; // [rsp+30h] [rbp-20h]
unsigned char *s; // [rsp+38h] [rbp-18h]
v3 = 3 * (len / 4);
v4 = 0;
v5 = 0;
if ( Str[len - 1] == '=' )
v4 = 1;
if ( Str[len - 2] == '=' )
++v4;
if ( Str[len - 3] == '=' )
++v4;
if ( v4 == 3 )
{
v3 += 2;
}
else if ( v4 <= 3 )
{
if ( v4 == 2 )
{
v3 += 3;
}
else if ( v4 <= 2 )
{
if ( v4 )
{
if ( v4 == 1 )
v3 += 4;
}
else
{
v3 += 4;
}
}
}
s =(unsigned char*)malloc(v3);
if ( s )
{
memset(s, 0, v3);
v10 = s;
while ( v5 < len - v4 )
{
v6 = 0;
v7 = 0;
while ( v6 <= 3 && v5 < len - v4 )
{
v7 = (v7 << 6) | (char)find_pos(Str[v5]);
++v6;
++v5;
}
v8 = v7 << 6 * (4 - v6);
for ( i = 0; i <= 2 && i != v6; ++i )
*v10++ = v8 >> 8 * (2 - i);
}
*v10 = 0;
result = s;
}
else
{
puts("No enough memory.");
result = 0LL;
}
return result;
}
void Solve(int a,int b,int c,int trys)
{
for(int i=0;i<strlen(table);i++)
for(int j=0;j<strlen(table);j++)
for(int k=0;k<strlen(table);k++)
for(int l=0;l<strlen(table);l++)
{
char test[4];
test[0]=table[i];
test[1]=table[j];
test[2]=table[k];
test[3]=table[l];
test[4]='\0';
unsigned char *str=(unsigned char *)RxEncode(test,4);
if(str[0]==a && str[1]==b && str[2]==c)
{
printf("%c%c%c%c %d\n",table[i],table[j],table[k],table[l],trys);
}
}
}//npuctf{w0w+y0U+cAn+r3lllY+dAnc3}
int main()
{
int data[25]={0x9E,0x9B,0x9C,0xB5,0xFE,0x70,0xD3,0x0F,0xB2,0xD1,0x4F,0x9C,0x02,0x7F,0xAB,0xDE,0x59,0x65,0x63,0xE7,0x40,0x9D,0xCD,0xFA};
for(int i=0;i<8;i++)
Solve(data[3*i],data[3*i+1],data[3*i+2],i);
return 0;
}