对于这个比赛呢,还是挺有感悟的,你一个人怎么和那些"几个队伍一起打的"对线,我也不知道该怎么说,我只能说打ctf的都懂我前面那句话,虽然我花了一天AK了逆向,但是也没用,hh…
看题吧,还是有些地方能够积累一些经验的
这道题应该算是一道签到题吧
看汇编
movzx edx, byte ptr [rbp-105]
movzx eax, byte ptr [rbp-104]
xor edx, eax
movzx eax, byte ptr [rbp-103]
xor eax, edx
mov [rbp-75h], al
取了flag中间的三个字节来异或得到一个值
然后将flag的所有字节都异或这个值
然后这个xor_data数据类型是char的,直接爆破255范围即可
cmp = [0x00000011, 0x0000011B, 0x00000216, 0x00000310, 0x0000040C, 0x00000546, 0x00000644, 0x00000711, 0x00000844, 0x00000942, 0x00000A41, 0x00000B41, 0x00000C44, 0x00000D5A, 0x00000E42, 0x00000F47, 0x00001016, 0x00001143, 0x0000125A, 0x00001343, 0x00001440, 0x00001540, 0x00001615, 0x0000175A, 0x00001845, 0x00001940, 0x00001A4F, 0x00001B15, 0x00001C5A, 0x00001D15, 0x00001E40, 0x00001F46, 0x00002046, 0x00002147, 0x00002245, 0x00002341, 0x00002411, 0x00002511, 0x00002640, 0x00002716, 0x00002813, 0x0000290A]
def all_see(arr):
cnt = 0
for k in range(len(arr)):
if (arr[k] > 32) and (arr[k] < 127):
cnt += 1
if cnt == len(arr):
return True
else:
return False
for i in range(255):
temp = []
for j in range(len(cmp)):
temp.append((cmp[j] ^ i) & 0xff)
if all_see(temp):
for m in range(len(temp)):
print(chr(temp[m]), end='')
print()
# test.py
1;60,fd1dbaadzbg6czc``5ze`o5z5`ffgea11`63*
0:71-ge0ec``e{cf7b{baa4{dan4{4aggfd`00a72+
3942.df3f`ccfx`e4axabb7xgbm7x7bddegc33b41(
2853/eg2gabbgyad5`y`cc6yfcl6y6ceedfb22c50)
5?24(b`5`fee`~fc2g~gdd1~adk1~1dbbcae55d27.
7=06*`b7bdggb|da0e|eff3|cfi3|3f``acg77f05,
6<17+ac6ceffc}e`1d}dgg2}bgh2}2gaa`bf66g14-
93>8$nl9ljiilrjo>krkhh=rmhg=r=hnnomi99h>;"
82?9%om8mkhhmskn?jsjii<slif<s<ioonlh88i?:#
:0=;'mo:oijjoqil=hqhkk>qnkd>q>kmmlnj::k=8!
<6;=!ki<iolliwoj;nwnmm8whmb8w8mkkjhl<<m;>'
?58>"hj?jloojtli8mtmnn;tkna;t;nhhiko??n8=$
>49?#ik>kmnnkumh9luloo:ujo`:u:oiihjn>>o9<%
#)$">tv#vpssvhpu$qhqrr'hwr}'h'rttuws##r$!8
%/"$8rp%pvuupnvs"wnwtt!nqt{!n!trrsqu%%t"'>
&,!';qs&suvvsmup!tmtww"mrwx"m"wqqprv&&w!$=
ys~xd.,y,*)),2*/~+2+((}2-('}2}(../-)yy(~{b
zp}{g-/z/)**/1),}(1(++~1.+$~1~+--,.*zz+}xa
|v{}a+)|)/,,)7/*{.7.--x7(-"x7x-++*(,||-{~g
akf`|64a42114*27f3*300e*50?e*e066751aa0fcz
`jga}75`53005+36g2+211d+41>d+d177640``1gb{
cidb~46c60336(05d1(122g(72=g(g244573cc2dax
eobdx20e06550.63b7.744a.14;a.a422315ee4bg~
gm`fz02g24772,41`5,566c,369c,c600137gg6`e|
flag{13f35663-50a4-477b-278b-b711026ff7ad}
icnht><i<:99<":?n;";88m"=87m"m8>>?=9ii8nkr
hboiu?=h=;88=#;>o:#:99l#<96l#l9??><8hh9ojs
j`mkw=?j?9::?!9<m8!8;;n!>;4n!n;==<>:jj;mhq
mgjlp:8m8>==8&>;j?&?<<i&9<3i&i<::;9=mm<jov
lfkmq;9l9?<<9'?:k>'>==h'8=2h'h=;;:8<ll=knw
oehnr8:o:<??:$<9h=$=>>k$;>1k$k>889;?oo>hmt
ndios9;n;=>>;%=8i<%<??j%:?0j%j?998:>nn?ilu
Process finished with exit code 0
有一些花指令导致ida反编译失败,修改修改
int __cdecl sub_401320(int a1)
{
int result; // eax
char v2; // [esp+0h] [ebp-3Ch]
char *v3; // [esp+10h] [ebp-2Ch]
char *Buffer; // [esp+14h] [ebp-28h]
signed int v5; // [esp+1Ch] [ebp-20h]
int i; // [esp+28h] [ebp-14h]
v5 = strlen(byte_4054A8);
length = v5;
if ( v5 % 3 == 1 )
{
Buffer = &byte_4054A8[length++];
sub_401020(Buffer, "=", v2);
}
else if ( v5 % 3 != 2 )
{
goto LABEL_6;
}
v3 = &byte_4054A8[length++];
sub_401020(v3, "=", v2);
LABEL_6:
for ( i = 0; i < length; i += 3 )
main_encrypt(byte_4054A8, i, a1);
result = v5 / 3;
if ( v5 % 3 == 1 )
return sub_401020((a1 + 4 * (v5 / 3)), "==", v2);
if ( v5 % 3 == 2 )
return sub_401020((a1 + 4 * (v5 / 3)), "=", v2);
return result;
}
int __cdecl main_encrypt(char *a1, int a2, char *a3)
{
int result; // eax
_BYTE v4[64]; // [esp+Ch] [ebp-40h] BYREF
memset(v4, 0xCCu, sizeof(v4));
a3[4 * (a2 / 3)] = aAbcdfegh1jklrs[((4 * (a1[a2 + 2] & 3)) | a1[a2 + 1] & 0x30 | a1[a2] & 0xC0) >> 2];
a3[4 * (a2 / 3) + 1] = aAbcdfegh1jklrs[((4 * (a1[a2] & 3)) | a1[a2 + 2] & 0x30 | a1[a2 + 1] & 0xC0) >> 2];
a3[4 * (a2 / 3) + 2] = aAbcdfegh1jklrs[((4 * (a1[a2 + 1] & 3)) | a1[a2] & 0x30 | a1[a2 + 2] & 0xC0) >> 2];
result = a2 / 3;
a3[4 * (a2 / 3) + 3] = aAbcdfegh1jklrs[(a1[a2 + 2] & 0xC | (4 * a1[a2 + 1]) & 0x30 | (16 * a1[a2]) & 0xC0) >> 2];
return result;
}
可以得到就是一个base64,但是是不可逆的
使用z3来求解
# _*_ coding: utf-8 _*_
# editor: SYJ
# function: Reversed By SYJ
"""
describe:
"""
import base64
changed = "ABCDFEGH1JKLRSTMNP0VWQUXY2a8cdefijklmnopghwxyqrstuvzOIZ34567b9+/"
base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
inp = b"0123456789abcdef=="
for i in range(0, len(inp), 3):
print(changed[((4 * (inp[i + 2] & 3)) | inp[i + 1] & 0x30 | inp[i] & 0xc0) >> 2], end='')
print(changed[((4 * (inp[i] & 3)) | inp[i + 2] & 0x30 | inp[i + 1] & 0xC0) >> 2], end='')
print(changed[((4 * (inp[i + 1] & 3)) | inp[i] & 0x30 | inp[i + 2] & 0xC0) >> 2], end='')
print(changed[(inp[i + 2] & 0xC | (4 * inp[i + 1]) & 0x30 | (16 * inp[i]) & 0xC0) >> 2], end='')
# 上面是试试加密是否对拍正确
print()
# 下面使用z3求解
from z3 import *
enflag = '2aYcdfL2fS1BTMMF1RSeMTTASS1OJ8RHTJdBYJ2STJfNMSMAYcKUJddp'
for i in range(0, len(enflag), 4):
flag_part = [BitVec(('x%d' % j), 8) for j in range(3)]
s = Solver()
for k in range(0, 3):
s.add(flag_part[k] < 127)
s.add(flag_part[k] > 32)
s.add(((4 * (flag_part[2] & 3)) | flag_part[1] & 0x30 | flag_part[0] & 0xc0) == changed.find(enflag[i]) << 2)
s.add(((4 * (flag_part[0] & 3)) | flag_part[2] & 0x30 | flag_part[1] & 0xC0) == changed.find(enflag[i+1]) << 2)
s.add(((4 * (flag_part[1] & 3)) | flag_part[0] & 0x30 | flag_part[2] & 0xC0) == changed.find(enflag[i+2]) << 2)
s.add((flag_part[2] & 0xC | (4 * flag_part[1]) & 0x30 | (16 * flag_part[0]) & 0xC0) == changed.find(enflag[i+3]) << 2)
if s.check() == sat:
model = s.model()
b = [chr(model[flag_part[m]].as_long().real) for m in range(3)]
flag_ = "".join(b)
print(flag_, end='')
else:
print("sorry!!!!!unsat!!!")
flag{5a073724-8223-413d-11fa-d53b133df89e}
一道apk,先看静态
关键逻辑
public native String stringFromJNI(String str, String str2);
stringFromJNI(MainActivity.this.input.getText().toString(), new C0374hi().getSignatures(view))
第一个参数是我们输入的字符串,第二个参数是获取的包的签名信息
解包后查看so文件
jstring __fastcall Java_com_example_hello_MainActivity_stringFromJNI(_JNIEnv *a1, __int64 a2, __int64 a3, __int64 a4)
{
int8x16_t *inp; // x20
const char *sign; // x0
const char *v8; // x21
unsigned __int64 i; // x23
unsigned int j; // w24
unsigned int v11; // w1
unsigned __int8 v12; // w9
unsigned int v13; // w11
unsigned int v14; // w12
unsigned int v15; // w13
unsigned int v16; // w14
unsigned int v17; // w15
int8x16_t v18; // q0
unsigned int v19; // w16
int8x16_t v20; // q1
unsigned int v21; // w17
__int64 k; // x8
const char *v23; // x21
jstring v24; // x19
char v26[16]; // [xsp+0h] [xbp-50h] BYREF
const char *v27; // [xsp+10h] [xbp-40h]
__int64 v28; // [xsp+18h] [xbp-38h]
v28 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
inp = (int8x16_t *)a1->functions->GetStringUTFChars(a1, a3, 0LL);
sign = a1->functions->GetStringUTFChars(a1, a4, 0LL);
if ( inp->n128_u8[0] )
{
v8 = sign;
inp->n128_u8[0] ^= sign[327]; // 0x66 ^ 0x30
if ( strlen((const char *)inp) >= 2uLL )
{
i = 1LL;
j = 354;
do
{
inp->n128_u8[i] ^= v8[j] + (_BYTE)i; // 异或回去即可
++i;
j += 27;
}
while ( strlen((const char *)inp) > i );
}
}
v11 = (inp[2].n128_u8[0] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[0]);
v12 = (inp[2].n128_u8[1] >> 3) & 31 | (32 * inp[2].n128_u8[1]);
v13 = (inp[2].n128_u8[3] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[3]);
v14 = (inp[2].n128_u8[4] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[4]);
v15 = (inp[2].n128_u8[5] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[5]);
v16 = (inp[2].n128_u8[6] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[6]);
v17 = (inp[2].n128_u8[7] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[7]);
v18 = vorrq_s8(vshrq_n_u8(*inp, 3uLL), vshlq_n_s8(*inp, 5uLL));
v19 = (inp[2].n128_u8[8] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[8]);
v20 = vorrq_s8(vshrq_n_u8(inp[1], 3uLL), vshlq_n_s8(inp[1], 5uLL));
v21 = (inp[2].n128_u8[9] >> 3) & 0xFFFFE01F | (32 * inp[2].n128_u8[9]);
inp[2].n128_u8[2] = (inp[2].n128_u8[2] >> 3) & 0x1F | (32 * inp[2].n128_u8[2]);
inp[2].n128_u8[0] = v11;
inp[2].n128_u8[1] = v12;
inp[2].n128_u8[3] = v13;
inp[2].n128_u8[4] = v14;
inp[2].n128_u8[5] = v15;
inp[2].n128_u8[6] = v16;
inp[2].n128_u8[7] = v17;
inp[2].n128_u8[8] = v19;
inp[2].n128_u8[9] = v21;
*inp = v18;
inp[1] = v20;
v26[15] = 0;
v26[0] = 26;
k = 0LL;
v27 = 0LL;
v23 = &v26[1];
strcpy(&v26[1], "Wrong, wrong!");
while ( inp->n128_u8[k] == byte_6F75D41460[k] )
{
if ( (unsigned __int64)++k > 0x29 )
{
std::string::assign(v26, "Hello, hello!", 13LL);
if ( (v26[0] & 1) != 0 )
v23 = v27;
break;
}
}
v24 = a1->functions->NewStringUTF(a1, v23);
if ( (v26[0] & 1) != 0 )
operator delete(v27);
return v24;
}
先和包的签名信息异或之后进行了位运算
然后想方法获取包的签名信息
在安装apk的时候报错
看了下AndroidManifest.xml
android:testOnly="true"
这个标记原本是用来标记测试用的,所以带这个标记的包一般情况下是不能安装上的
本想修改一下这个为false,然后重新打包,但是在签名的时候会改掉它原来的签名
然后进行了资料查找之后
-t测试package标志
adb install -t test.apk #allow test packages
然后就安装上了,直接调试获取到签名
解题脚本:
crt是我们提取的签名数据
crt
date = open(r'D:\CTF\COMPETITIONS\2021dhb\Re\hello\crt', 'rb').read()
good = []
for i in range(42):
for j in range(0xff):
if ((j >> 3) & 0xFFFFE01F | (j << 5)) & 0xff == cmp[i]:
good.append(j)
for i in range(42):
# print(hex(temp[i] ^ (date[327+i*27] + i)), end=', ')
print(chr((good[i] ^ (date[327+i*27] + i))), end='')
flag{d5577edd-8211-7a0e-f23a-305b0b10683f}
一道32位程序调用了64位程序的
参考资料:https://www.anquanke.com/post/id/171111
如果此时栈中有0x33,则会将0x33弹出到CS寄存器中,实现32位程序切换到64位代码的过程。所以retf是识别32位程序调用64位代码的重要标志。
LONG __stdcall Handler(struct _EXCEPTION_POINTERS *ExceptionInfo)
{
HANDLE CurrentProcess; // eax
NTSTATUS (__stdcall *NtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG); // [esp+10h] [ebp-10h]
HMODULE hModule; // [esp+14h] [ebp-Ch]
int dwDebugport; // [esp+18h] [ebp-8h] BYREF
if ( ExceptionInfo->ContextRecord->Eip != &loc_416DFF )
return 0;
hModule = LoadLibraryA(LibFileName); // ntdll.dll
if ( !hModule )
_loaddll(0);
NtQueryInformationProcess = GetProcAddress(hModule, aNtqueryinforma);
if ( !NtQueryInformationProcess ) // NtQueryInformationProcess
_loaddll(0);
dwDebugport = 0;
CurrentProcess = GetCurrentProcess();
if ( (NtQueryInformationProcess)(CurrentProcess, 7, &dwDebugport, 4, 0) || !dwDebugport )// 调试处于0xffffffff, 非调试处于0
{
sub_4174C0(*(ExceptionInfo->ContextRecord->Ebp + 8));// 非调试进入该函数
return _loaddll(0);
}
else
{
ExceptionInfo->ContextRecord->Eax = ExceptionInfo->ContextRecord->Eax;
ExceptionInfo->ContextRecord->Ecx = ExceptionInfo->ContextRecord->Ecx;
return -1;
}
}
关键逻辑在sub_4174C0中
有许多小函数,进小函数之后就反编译失败,全是JUMPOUT
查看汇编
32位调用64位的特征
说明后面那些机器码是64位的
我们直接PE文件头中标识程序为32位的修改为64然后拖入ida
类似如下:
void __fastcall __noreturn sub_41730F(int a1, int a2)
{
void *retaddr[2]; // [rsp+0h] [rbp+0h]
LODWORD(retaddr[1]) = a1;
dword_420400[a1] = *(_DWORD *)(unsigned int)(a2 + dword_4203E0);
}
就可以知道这个函数做了什么
然后全部
BOOL __cdecl sub_4174C0(void *lpBuffer)
{
HANDLE StdHandle; // eax
BOOL result; // eax
HANDLE v3; // eax
HANDLE v4; // eax
HANDLE v5; // eax
HANDLE v6; // eax
HANDLE v7; // eax
HANDLE v8; // eax
HANDLE v9; // eax
HANDLE v10; // eax
HANDLE v11; // eax
HANDLE v12; // eax
HANDLE v13; // eax
int v14; // [esp-78h] [ebp-94h]
int v15; // [esp-68h] [ebp-84h]
int v16; // [esp-54h] [ebp-70h]
int v17; // [esp-48h] [ebp-64h]
int v18; // [esp-40h] [ebp-5Ch]
int v19; // [esp-38h] [ebp-54h]
int v20; // [esp-34h] [ebp-50h]
int v21; // [esp-30h] [ebp-4Ch]
int v22; // [esp-28h] [ebp-44h]
int v23; // [esp-14h] [ebp-30h]
int v24; // [esp-8h] [ebp-24h]
int k; // [esp+0h] [ebp-1Ch]
int v26; // [esp+0h] [ebp-1Ch]
int m; // [esp+4h] [ebp-18h]
int i; // [esp+8h] [ebp-14h]
int j; // [esp+Ch] [ebp-10h]
__int64 Buffer; // [esp+10h] [ebp-Ch] BYREF
int v31; // [esp+18h] [ebp-4h]
sub_4173E0();
for ( i = 0; i < 32; ++i )
*(i + dword_4203E0) = *(lpBuffer + i);
(sub_4171B0)(0, 0x12345678); // dword_420400[0] = 0x12345678
(sub_4171B0)(1, 0x87654321); // dword_420400[a1] = a2
(sub_4171B0)(2, 0x13243546);
(sub_4171B0)(3, 0x64534231);
sub_417370(); // *(a1 + dword_4203E0) = dword_420400[a2]
sub_417370(); // dword_4203E0内存开始的32 40 48 56 64存放了这5个值
sub_417370();
sub_417370();
(sub_4171B0)(0, 0xB879379E);
sub_417370();
for ( j = 0; j < 32; j += 8 )
{
sub_417300(); // dword_420400[0] = *(32 + dword_4203E0)
sub_417300(); // dword_420400[1] = *(36 + dword_4203E0)
sub_417370(); // *(72 + dword_4203E0) = dword_420400[0]
sub_417370(); // *(80 + dword_4203E0) = dword_420400[1]
(sub_4171B0)(0, 0, v14); // dword_420400[0] = 0
sub_417370(); // *(88 + dword_4203E0) = dword_420400[0]
for ( k = 0; k < 16; k = v26 + 1 )
{
sub_417300(); // dword_420400[0] = *(88 + dword_4203E0)
sub_417300(); // dword_420400[1] = *(64 + dword_4203E0)
(sub_417290)(0, 1, v15); // dword_420400[0] += dword_420400[1]
sub_417370(); // *(88 + dword_4203E0) = dword_420400[0]
sub_417300(); // dword_420400[0] = *(80 + dword_4203E0)
sub_417140(); // dword_420400[0] <<= 4
sub_417300(); // dword_420400[1] = *(32 + dword_4203E0)
(sub_417290)(0, 1, v16); // dword_420400[0] += dword_420400[1]
sub_417300(); // dword_420400[1] = *(80 + dword_4203E0)
sub_417300(); // dword_420400[2] = *(88 + dword_4203E0)
(sub_417290)(1, 2, v17); // dword_420400[1] += dword_420400[2]
sub_417300(); // dword_420400[2] = *(80 + dword_4203E0)
(sub_4170D0)(2, 5, v18); // dword_420400[2] >>= 5
sub_417300(); // dword_420400[3] = *(40 + dword_4203E0)
(sub_417290)(2, 3, v19); // dword_420400[2] += dword_420400[3]
(sub_417220)(1, 2, v20); // dword_420400[1] ^= dword_420400[2]
(sub_417220)(0, 1, v21); // dword_420400[0] ^= dword_420400[1]
sub_417300(); // dword_420400[1] = *(72 + dword_4203E0)
(sub_417290)(1, 0, v22); // dword_420400[1] += dword_420400[0]
sub_417370(); // *(72 + dword_4203E0) = dword_420400[1]
sub_417300(); // dword_420400[0] = *(72 + dword_4203E0)
sub_417140(); // dword_420400[0] <<= 4
sub_417300(); // dword_420400[1] = *(48 + dword_4203E0)
(sub_417290)(0, 1, v23); // dword_420400[0] += dword_420400[1]
sub_417300(); // dword_420400[1] = *(72 + dword_4203E0)
sub_417300(); // dword_420400[2] = *(88 + dword_4203E0)
(sub_417290)(1, 2, v24); // dword_420400[1] += dword_420400[2]
sub_417300(); // dword_420400[2] = *(72 + dword_4203E0)
(sub_4170D0)(2, 5, k); // dword_420400[2] >>= 5
sub_417300(); // dword_420400[3] = *(56 + dword_4203E0)
(sub_417290)(2, 3, i); // dword_420400[2] += dword_420400[3]
(sub_417220)(1, 2, j); // dword_420400[1] ^= dword_420400[2]
(sub_417220)(0, 1, Buffer); // dword_420400[0] ^= dword_420400[1]
sub_417300(); // dword_420400[1] = *(80 + dword_4203E0)
(sub_417290)(1, 0, v31); // dword_420400[1] += dword_420400[0]
sub_417370(); // *(80 + dword_4203E0) = dword_420400[1]
}
sub_417300(); // dword_420400[0] = *(72 + dword_4203E0)
sub_417300(); // dword_420400[1] = *(80 + dword_4203E0)
sub_417370(); // *(j + dword_4203E0) = dword_420400[0]
sub_417370(); // *(j+4 + dword_4203E0) = dword_420400[1]
// *(_DWORD *)(unsigned int)(a1 + dword_4203E0) = dword_420400[a2]
}
strcpy(&Buffer, "right\n");
HIBYTE(Buffer) = 0;
for ( m = 0; m < 32; ++m )
{
if ( *(m + dword_4203E0) != *(off_41F8D4 + m) )
{
strcpy(&Buffer, "wrong\n");
HIBYTE(Buffer) = 0;
break;
}
}
StdHandle = GetStdHandle(0xFFFFFFF5);
result = WriteConsoleA(StdHandle, &Buffer, 6u, 0, 0);
if ( Buffer == '\nthgir' )
{
Buffer = '{galf';
v3 = GetStdHandle(0xFFFFFFF5);
WriteConsoleA(v3, &Buffer, 6u, 0, 0);
v4 = GetStdHandle(0xFFFFFFF5);
WriteConsoleA(v4, lpBuffer, 8u, 0, 0);
v5 = GetStdHandle(0xFFFFFFF5);
WriteConsoleA(v5, asc_41F9A4, 1u, 0, 0);
v6 = GetStdHandle(0xFFFFFFF5);
WriteConsoleA(v6, lpBuffer + 8, 4u, 0, 0);
v7 = GetStdHandle(0xFFFFFFF5);
WriteConsoleA(v7, asc_41F9A0, 1u, 0, 0);
v8 = GetStdHandle(0xFFFFFFF5);
WriteConsoleA(v8, lpBuffer + 12, 4u, 0, 0);
v9 = GetStdHandle(0xFFFFFFF5);
WriteConsoleA(v9, asc_41F99C, 1u, 0, 0);
v10 = GetStdHandle(0xFFFFFFF5);
WriteConsoleA(v10, lpBuffer + 16, 4u, 0, 0);
v11 = GetStdHandle(0xFFFFFFF5);
WriteConsoleA(v11, asc_41F998, 1u, 0, 0);
v12 = GetStdHandle(0xFFFFFFF5);
WriteConsoleA(v12, lpBuffer + 20, 0xCu, 0, 0);
v13 = GetStdHandle(0xFFFFFFF5);
return WriteConsoleA(v13, asc_41F994, 1u, 0, 0);
}
return result;
}
可以得到关键的加密逻辑
解题脚本:
#include
#include
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t delta=0xB879379E;
uint32_t v0=v[0], v1=v[1], sum=(delta*16)&0xffffffff, i;
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
for (i=0; i<16; i++)
{
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
}
v[0]=v0; v[1]=v1;
}
int main()
{
uint32_t array[] = {0x2C94650B, 0x78494E9E, 0xE7FACF44, 0x48F9DBFB, 0x547BB145, 0x925D2542, 0x69A9F4C4, 0x9A96A1D8};
uint32_t key[4] = {0x12345678,0x87654321,0x13243546,0x64534231};
int i = 0;
for(i=0;i<8;i+=2)
{
uint32_t temp[2];
temp[0] = array[i];
temp[1] = array[i+1];
decrypt(temp, key);
//printf("%c%c%c%c%c%c%c%c",*((char*)&temp[0]+3),*((char*)&temp[0]+2),*((char*)&temp[0]+1),*((char*)&temp[0]+0),*((char*)&temp[1]+3),*((char*)&temp[1]+2),*((char*)&temp[1]+1),*((char*)&temp[1]+0));
printf("%c%c%c%c%c%c%c%c",*((char*)&temp[0]+0),*((char*)&temp[0]+1),*((char*)&temp[0]+2),*((char*)&temp[0]+3),*((char*)&temp[1]+0),*((char*)&temp[1]+1),*((char*)&temp[1]+2),*((char*)&temp[1]+3));
}
return 0;
}
flag{0f4d0db3668dd58cabb9eb409657eaa8}