-
-
[原创]2019看雪CTF 晋级赛Q2 第4题-达芬奇密码
-
发表于: 2019-6-24 14:30 4796
-
程序主逻辑在sub_1201EA0函数中,有如下条件:
输入字符串长度为》=16。
checkFun()函数返回ture为正确结果,而
checkFun()为加密函数,需要解密还原。
int __thiscall sub_1201EA0(CWnd *this) { CWnd *v1; // esi int v2; // eax WCHAR String; // [esp+Ch] [ebp-310h] char v5; // [esp+Eh] [ebp-30Eh] char key; // [esp+20Ch] [ebp-110h] char v7; // [esp+20Dh] [ebp-10Fh] DWORD v8; // [esp+30Ch] [ebp-10h] CWnd *v9; // [esp+310h] [ebp-Ch] int v10; // [esp+314h] [ebp-8h] DWORD flOldProtect; // [esp+318h] [ebp-4h] v1 = this; v9 = this; String = 0; memset(&v5, 0, 0x1FEu); key = 0; memset(&v7, 0, 0xFFu); CWnd::GetDlgItemTextW(v1, 1000, &String, 20); if ( wcslen(&String) == 16 ) { v2 = 0; while ( !(*(&String + v2) & 0xFF00) ) { *(&key + v2) = *((_BYTE *)&String + 2 * v2); if ( ++v2 >= 16 ) { v8 = 64; flOldProtect = 0; VirtualProtect(checkFun, 0xD17u, 0x40u, &flOldProtect); if ( GetLastError() ) return CWnd::MessageBoxW(v1, L"Wrong!", 0, 0); qmemcpy(checkFun, byte_13647B8, 0x330u); VirtualProtect(checkFun, 0xD17u, flOldProtect, &v8); if ( !GetLastError() ) { v10 = 0; v10 = checkFun(&key); if ( v10 == 1 ) return CWnd::MessageBoxW(v9, L"Congratulations! You are right!", 0, 0); } v1 = v9; return CWnd::MessageBoxW(v1, L"Wrong!", 0, 0); } } }
还原checkFun函数
int __thiscall sub_1201EA0(CWnd *this) { CWnd *v1; // esi int v2; // eax WCHAR String; // [esp+Ch] [ebp-310h] char v5; // [esp+Eh] [ebp-30Eh] char key; // [esp+20Ch] [ebp-110h] char v7; // [esp+20Dh] [ebp-10Fh] DWORD v8; // [esp+30Ch] [ebp-10h] CWnd *v9; // [esp+310h] [ebp-Ch] int v10; // [esp+314h] [ebp-8h] DWORD flOldProtect; // [esp+318h] [ebp-4h] v1 = this; v9 = this; String = 0; memset(&v5, 0, 0x1FEu); key = 0; memset(&v7, 0, 0xFFu); CWnd::GetDlgItemTextW(v1, 1000, &String, 20); if ( wcslen(&String) == 16 ) { v2 = 0; while ( !(*(&String + v2) & 0xFF00) ) { *(&key + v2) = *((_BYTE *)&String + 2 * v2); if ( ++v2 >= 16 ) { v8 = 64; flOldProtect = 0; VirtualProtect(checkFun, 0xD17u, 0x40u, &flOldProtect); if ( GetLastError() ) return CWnd::MessageBoxW(v1, L"Wrong!", 0, 0); qmemcpy(checkFun, byte_13647B8, 0x330u); VirtualProtect(checkFun, 0xD17u, flOldProtect, &v8); if ( !GetLastError() ) { v10 = 0; v10 = checkFun(&key); if ( v10 == 1 ) return CWnd::MessageBoxW(v9, L"Congratulations! You are right!", 0, 0); } v1 = v9; return CWnd::MessageBoxW(v1, L"Wrong!", 0, 0); } } }
qmemcpy(checkFun, byte_13647B8, 0x330u);可以看到从全局变量地址
byte_13647B8 还原了0x330bytes数据。查看
byte_13647B8引用。
do { byte_13647B8[v2] ^= 0xABu; ++v2; } while ( v2 < 0x330 );
初始化时有个以或0xAB操作。我们可以将原始的exe文件解密还原另存为新的exe文件继续分析。
do { byte_13647B8[v2] ^= 0xABu; ++v2; } while ( v2 < 0x330 );
初始化时有个以或0xAB操作。我们可以将原始的exe文件解密还原另存为新的exe文件继续分析。
signed int __cdecl checkFun(char *key) { signed int index; // eax char v2; // cl signed int v3; // ecx signed int v4; // eax signed int v5; // eax signed int i; // esi signed int v7; // ecx __int16 curKey_low; // dx _BYTE *v9; // edi __int16 v10; // ax signed int v11; // eax signed int v12; // ecx unsigned __int16 v13; // bx signed int v14; // esi signed int v15; // ecx __int16 v16; // dx _BYTE *v17; // edi __int16 v18; // ax signed int v19; // eax signed int v20; // ecx unsigned __int16 v21; // bx unsigned int v22; // eax signed int v23; // ecx unsigned __int16 v24; // dx char v25; // dl signed int v26; // eax __int16 v27; // si int v28; // eax _BYTE v30[8]; // [esp+8h] [ebp-90h] _BYTE v31[8]; // [esp+10h] [ebp-88h] int v32; // [esp+18h] [ebp-80h] int v33; // [esp+1Ch] [ebp-7Ch] int v34; // [esp+20h] [ebp-78h] int v35; // [esp+24h] [ebp-74h] _BYTE key_low[8]; // [esp+28h] [ebp-70h] _BYTE v37[8]; // [esp+30h] [ebp-68h] _BYTE v38[8]; // [esp+38h] [ebp-60h] _BYTE key_high[8]; // [esp+40h] [ebp-58h] _BYTE v40[40]; // [esp+48h] [ebp-50h] _BYTE v41[40]; // [esp+70h] [ebp-28h] v30[4] = 0x81u; v31[3] = 0x81u; index = 0; v30[0] = 0x16; v30[1] = 0x96u; v30[2] = 0x8Cu; v30[3] = 0xE3u; v30[5] = 0x98u; v30[6] = 0x6E; v30[7] = 0x64; v31[0] = 0x84u; v31[1] = 8; v31[2] = 0xDCu; v31[4] = 0xBEu; v31[5] = 0x4D; v31[6] = 0x48; v31[7] = 0x4F; v32 = 0; v33 = 0; v34 = 0; v35 = 0; *(_DWORD *)key_low = 0; *(_DWORD *)&key_low[4] = 0; *(_DWORD *)key_high = 0; *(_DWORD *)&key_high[4] = 0; do { v2 = v31[index] ^ key[index + 8]; key_low[index] = v30[index] ^ v30[index + key - v30]; key_high[index++] = v2; } while ( index < 8 ); *(_DWORD *)v30 = 0; *(_DWORD *)v41 = 0; *(_DWORD *)&v41[4] = 0; *(_DWORD *)&v41[8] = 0; *(_DWORD *)&v41[12] = 0; v41[16] = 0; *(_DWORD *)&v41[20] = 0; *(_DWORD *)&v41[24] = 0; *(_DWORD *)&v41[28] = 0; *(_DWORD *)&v41[32] = 0; v41[36] = 0; *(_DWORD *)v40 = 0; *(_DWORD *)&v40[4] = 0; *(_DWORD *)&v40[8] = 0; *(_DWORD *)&v40[12] = 0; v40[16] = 0; *(_DWORD *)&v40[20] = 0; *(_DWORD *)&v40[24] = 0; *(_DWORD *)&v40[28] = 0; *(_DWORD *)&v40[32] = 0; v40[36] = 0; *(_DWORD *)&v30[4] = 0; *(_DWORD *)v31 = 0; *(_DWORD *)&v31[4] = 0; LOBYTE(v32) = 0; v3 = 8; v30[0] = 8; v4 = 7; do { if ( key_low[v4] ) break; --v3; --v4; } while ( v4 >= 0 ); if ( v3 == 8 ) { v5 = 7; do { if ( key_high[v5] ) break; --v3; --v5; } while ( v5 >= 0 ); if ( v3 == 8 && !(key_low[7] & 0xF0) ) // 高四位为0 { i = 0; do { *(_DWORD *)v37 = 0; *(_DWORD *)&v37[4] = 0; *(_DWORD *)v38 = 0; *(_DWORD *)&v38[4] = 0; v7 = 0; curKey_low = (unsigned __int8)key_low[i]; v9 = &v37[i]; do { v10 = (unsigned __int8)v38[i] + curKey_low * (unsigned __int8)key_low[v7]; v9[v7] = v38[i] + curKey_low * key_low[v7]; ++v7; v38[i] = HIBYTE(v10); } while ( v7 < 8 ); LOBYTE(v11) = 0; v12 = 0; do { v13 = (char)v11 + (unsigned __int8)v41[v12 + i] + (unsigned __int8)v9[v12]; v41[v12++ + i] = v13; v11 = (signed int)v13 >> 8; } while ( v12 < 9 ); ++i; } while ( i < 8 ); v14 = 0; do { *(_DWORD *)v37 = 0; *(_DWORD *)&v37[4] = 0; *(_DWORD *)v38 = 0; *(_DWORD *)&v38[4] = 0; v15 = 0; v16 = (unsigned __int8)key_high[v14]; v17 = &v37[v14]; do { v18 = (unsigned __int8)v38[v14] + v16 * (unsigned __int8)key_high[v15]; v17[v15] = v38[v14] + v16 * key_high[v15]; ++v15; v38[v14] = HIBYTE(v18); } while ( v15 < 8 ); LOBYTE(v19) = 0; v20 = 0; do { v21 = (char)v19 + (unsigned __int8)v41[v20 + 0x14 + v14] + (unsigned __int8)v17[v20]; v41[v20++ + 20 + v14] = v21; v19 = (signed int)v21 >> 8; } while ( v20 < 9 ); ++v14; } while ( v14 < 8 ); LOBYTE(v22) = v40[0x10]; v23 = 0; do { v24 = (unsigned __int8)v22 + 7 * (unsigned __int8)v41[v23 + 0x14]; v40[v23++] = v24; v22 = (unsigned int)v24 >> 8; } while ( v23 < 17 ); v40[16] = HIBYTE(v24); v25 = 0; v26 = 0; do { v27 = (unsigned __int8)v41[v26] - (unsigned __int8)v40[v26] - v25; v40[v26 + 0x14] = v27; if ( v27 < 0 ) v25 = 1; ++v26; } while ( v26 < 17 ); if ( !v25 ) { v28 = 0; while ( v40[v28 + 0x14] == v30[v28] ) { if ( ++v28 >= 17 ) return 1; } } } } return 0; }
该函数完成了一个算式检查。x^2-7y^2=8。其中有个限制条件X的高四位为0,x+y长度》=16
signed int __cdecl checkFun(char *key) { signed int index; // eax char v2; // cl signed int v3; // ecx signed int v4; // eax signed int v5; // eax signed int i; // esi signed int v7; // ecx __int16 curKey_low; // dx _BYTE *v9; // edi __int16 v10; // ax signed int v11; // eax signed int v12; // ecx unsigned __int16 v13; // bx signed int v14; // esi signed int v15; // ecx __int16 v16; // dx _BYTE *v17; // edi __int16 v18; // ax signed int v19; // eax signed int v20; // ecx unsigned __int16 v21; // bx unsigned int v22; // eax signed int v23; // ecx unsigned __int16 v24; // dx char v25; // dl signed int v26; // eax __int16 v27; // si int v28; // eax _BYTE v30[8]; // [esp+8h] [ebp-90h] _BYTE v31[8]; // [esp+10h] [ebp-88h] int v32; // [esp+18h] [ebp-80h] int v33; // [esp+1Ch] [ebp-7Ch] int v34; // [esp+20h] [ebp-78h] int v35; // [esp+24h] [ebp-74h] _BYTE key_low[8]; // [esp+28h] [ebp-70h] _BYTE v37[8]; // [esp+30h] [ebp-68h] _BYTE v38[8]; // [esp+38h] [ebp-60h] _BYTE key_high[8]; // [esp+40h] [ebp-58h] _BYTE v40[40]; // [esp+48h] [ebp-50h] _BYTE v41[40]; // [esp+70h] [ebp-28h] v30[4] = 0x81u; v31[3] = 0x81u; index = 0; v30[0] = 0x16; v30[1] = 0x96u; v30[2] = 0x8Cu; v30[3] = 0xE3u; v30[5] = 0x98u; v30[6] = 0x6E; v30[7] = 0x64; v31[0] = 0x84u; v31[1] = 8; v31[2] = 0xDCu; v31[4] = 0xBEu; v31[5] = 0x4D; v31[6] = 0x48; v31[7] = 0x4F; v32 = 0; v33 = 0; v34 = 0; v35 = 0; *(_DWORD *)key_low = 0; *(_DWORD *)&key_low[4] = 0; *(_DWORD *)key_high = 0; *(_DWORD *)&key_high[4] = 0; do { v2 = v31[index] ^ key[index + 8]; key_low[index] = v30[index] ^ v30[index + key - v30]; key_high[index++] = v2; } while ( index < 8 ); *(_DWORD *)v30 = 0; *(_DWORD *)v41 = 0; *(_DWORD *)&v41[4] = 0; *(_DWORD *)&v41[8] = 0; *(_DWORD *)&v41[12] = 0; v41[16] = 0; *(_DWORD *)&v41[20] = 0; *(_DWORD *)&v41[24] = 0; *(_DWORD *)&v41[28] = 0; *(_DWORD *)&v41[32] = 0; v41[36] = 0; *(_DWORD *)v40 = 0; *(_DWORD *)&v40[4] = 0; *(_DWORD *)&v40[8] = 0; *(_DWORD *)&v40[12] = 0; v40[16] = 0; *(_DWORD *)&v40[20] = 0; *(_DWORD *)&v40[24] = 0; *(_DWORD *)&v40[28] = 0; *(_DWORD *)&v40[32] = 0; v40[36] = 0; *(_DWORD *)&v30[4] = 0; *(_DWORD *)v31 = 0; *(_DWORD *)&v31[4] = 0; LOBYTE(v32) = 0; v3 = 8; v30[0] = 8; v4 = 7; do { if ( key_low[v4] ) break; --v3; --v4; } while ( v4 >= 0 ); if ( v3 == 8 ) { v5 = 7; do { if ( key_high[v5] ) break; --v3; --v5; } while ( v5 >= 0 ); if ( v3 == 8 && !(key_low[7] & 0xF0) ) // 高四位为0 { i = 0; do { *(_DWORD *)v37 = 0; *(_DWORD *)&v37[4] = 0; *(_DWORD *)v38 = 0; *(_DWORD *)&v38[4] = 0; v7 = 0; curKey_low = (unsigned __int8)key_low[i]; v9 = &v37[i]; do { v10 = (unsigned __int8)v38[i] + curKey_low * (unsigned __int8)key_low[v7]; v9[v7] = v38[i] + curKey_low * key_low[v7]; ++v7; v38[i] = HIBYTE(v10); } while ( v7 < 8 ); LOBYTE(v11) = 0; v12 = 0; do { v13 = (char)v11 + (unsigned __int8)v41[v12 + i] + (unsigned __int8)v9[v12]; v41[v12++ + i] = v13; v11 = (signed int)v13 >> 8; } while ( v12 < 9 ); ++i; } while ( i < 8 ); v14 = 0; do { *(_DWORD *)v37 = 0; *(_DWORD *)&v37[4] = 0; *(_DWORD *)v38 = 0; *(_DWORD *)&v38[4] = 0; v15 = 0; v16 = (unsigned __int8)key_high[v14]; v17 = &v37[v14]; do { v18 = (unsigned __int8)v38[v14] + v16 * (unsigned __int8)key_high[v15]; v17[v15] = v38[v14] + v16 * key_high[v15]; ++v15; v38[v14] = HIBYTE(v18); } while ( v15 < 8 ); LOBYTE(v19) = 0; v20 = 0; do { v21 = (char)v19 + (unsigned __int8)v41[v20 + 0x14 + v14] + (unsigned __int8)v17[v20]; v41[v20++ + 20 + v14] = v21; v19 = (signed int)v21 >> 8; } while ( v20 < 9 ); ++v14; } while ( v14 < 8 ); LOBYTE(v22) = v40[0x10]; v23 = 0; do { v24 = (unsigned __int8)v22 + 7 * (unsigned __int8)v41[v23 + 0x14]; v40[v23++] = v24; v22 = (unsigned int)v24 >> 8; } while ( v23 < 17 ); v40[16] = HIBYTE(v24); v25 = 0; v26 = 0; do { v27 = (unsigned __int8)v41[v26] - (unsigned __int8)v40[v26] - v25; v40[v26 + 0x14] = v27; if ( v27 < 0 ) v25 = 1; ++v26; } while ( v26 < 17 ); if ( !v25 ) { v28 = 0; while ( v40[v28 + 0x14] == v30[v28] ) { if ( ++v28 >= 17 ) return 1; } } } } return 0; }
该函数完成了一个算式检查。x^2-7y^2=8。其中有个限制条件X的高四位为0,x+y长度》=16
这是一个非标的佩尔方程,通解原理网上比较多,不说了。
// CTF4new.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
using namespace std;
typedef long long ll;
//const int mod = 8191;
const ll mod = 0x1fffffffffffffff;
struct matrix{ ll a[2][2]; matrix(){ memset(a, 0, sizeof(a)); } };
matrix ans;
ll xp = 0;
ll yp = 0;
ll x = 0;
ll y = 0;
matrix multi(matrix a, matrix b)
{
matrix ans;
for (int i = 0; i<2; i++)
for (int j = 0; j<2; j++)
for (int k = 0; k<2; k++)
ans.a[i][j] = (ans.a[i][j] + a.a[i][k] * b.a[k][j] % mod) % mod;
return ans;
}
matrix qpow(matrix res, ll k)
{
while (k)
{
if (k & 1)
res = multi(res, ans);
k /= 2;
ans = multi(ans, ans);
}
return res;
}
int main()
{
ll n, k;
n = 7;
k = 1;
while (k<=0x1000)
{
ll nn = sqrt(n), keepx, keepy;
if (nn*nn == n){ printf("No answers can meet such conditions\n"); continue; }
for (int i = 1;; i++)
{
ll y = i*i*n + 1;
ll yy = sqrt(y);
if (yy*yy == i*i*n + 1)
{
keepy = i;
keepx = yy;
//printf("x=%llx--y=%llx\n",keepx,keepy);
break;
}
}
ans.a[0][0] = keepx%mod;
ans.a[0][1] = n*keepy%mod;
ans.a[1][0] = keepy%mod;
ans.a[1][1] = keepx%mod;
matrix res;
res.a[0][0] = 1, res.a[1][1] = 1;
matrix ans = qpow(res, k - 1);
xp = (ans.a[0][0] * keepx%mod + ans.a[0][1] * keepy%mod + mod) % mod;
yp = (ans.a[1][0] * keepx%mod + ans.a[1][1] * keepy%mod + mod) % mod;
x = 6 * xp + 7 * 2 * yp;
y = 6 * yp + xp * 2;
//printf("%llx--%llx\n", x, y);
k++;
//05xxxxxxxxxxxxxx
//(0x100000000000000<x<0x1000000000000000)
if (x<0x100000000000000)
{
continue;
}
if (x>0x1000000000000000)
{
break;
}
printf("%llx--%llx\n", x, y);
}
return 0;
}
根据限制条件,找到已给特解:
557f3b3b9e1a55a--2050988b2bd38de
constLow = {0x16,0x96,0x8C,0xE3,0x81,0x98,0x6E,0x64};
constHigh = {0x84,8, 0xDC,0x81,0xBE,0x4D,0x48,0x4F};
异或常量后得到flag:L3mZ2k9aZ0a36DMM
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
看原图
赞赏
雪币:
留言: