INT_PTR __stdcall DialogFunc(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{const char *v4; // esiconst char *v5; // ediint v7[2]; // [esp+8h] [ebp-20030h] BYREF 虽然看名称不连续,但是通过看偏移地址,可知,这些变量在内存中是连续的,以v7为首int v8; // [esp+10h] [ebp-20028h]int v9; // [esp+14h] [ebp-20024h]int v10; // [esp+18h] [ebp-20020h]int v11; // [esp+1Ch] [ebp-2001Ch]int v12; // [esp+20h] [ebp-20018h]int v13; // [esp+24h] [ebp-20014h]int v14; // [esp+28h] [ebp-20010h]int v15; // [esp+2Ch] [ebp-2000Ch]int v16; // [esp+30h] [ebp-20008h]CHAR String[65536]; // [esp+34h] [ebp-20004h] BYREFchar v18[65536]; // [esp+10034h] [ebp-10004h] BYREFif ( a2 == 272 )return 1;if ( a2 != 273 )return 0;if ( (_WORD)a3 == 1001 ){memset(String, 0, 0xFFFFu);GetDlgItemTextA(hDlg, 1000, String, 0xFFFF);if ( strlen(String) == 8 ) // 输入的flag,可知为8位{v7[0] = 90;v7[1] = 74;v8 = 83;v9 = 69;v10 = 67;v11 = 97;v12 = 78;v13 = 72;v14 = 51;v15 = 110;v16 = 103;sub_8210F0((int)v7, 0, 10); // 在v7原来内存中进行修改,修改为3CEHJNSZagnmemset(v18, 0, 0xFFFFu);v18[0] = String[5];v18[2] = String[7];v18[1] = String[6];v4 = sub_821000((int)v18, strlen(v18)); // 字符串678位memset(v18, 0, 0xFFFFu);v18[1] = String[3];v18[0] = String[2];v18[2] = String[4];v5 = sub_821000((int)v18, strlen(v18)); // 字符串的345位if ( String[0] == v7[0] + 34 // string[0]=chr(ord('3')+34)='U'&& String[1] == v10 // string[1]='J'&& 4 * String[2] - 141 == 3 * v8 // string[2]=chr((3*ord('E')+141)//4)='W',注意这里直接除除不尽,需要向下取整&& String[3] / 4 == 2 * (v13 / 9) // string[3]=chr((2*(ord('Z')//9))*4)=‘P’,同样用到了向下取整&& !strcmp(v4, "ak1w") // base64解密后678位:jMp&& !strcmp(v5,"V1Ax") ){ // base64解密后345位:WP1MessageBoxA(hDlg, "U g3t 1T!", "@_@", 0);// 显示对话框,即成功}} // 最后string为:UJWP1jMpreturn 0;}if ( (_WORD)a3 != 1 && (_WORD)a3 != 2 )return 0;EndDialog(hDlg, (unsigned __int16)a3);return 1;
}
上图是主要分析的代码(思路:获取中间变量+倒推)
下图代码用于获得中间变量:(逆向功能:算法分析)
需要修改的地方:
1.在伪代码中,有a1+ 4 * i,a1+4 *result,这样的字符。int占四个字节,所以需要*4.如果是char类型,就不需要.
2.我们知道a1+4*i,也就是a1【i】,a1+4 * result,也就是a1【result】。
将伪代码的寻址方式改为数组寻址,然后将*(_DWORD*) 删掉,因为这是汇编的表示。
所以伪代码变成了C语言代码。
上代码:
#include <stdio.h>
int sub_8210F0(char* a1, int a2, int a3)//这算不算逆向的一个功能: 内部算法的了解分析
{int result; // eaxint i; // esiint v5; // ecxint v6; // edxresult = a3;for ( i = a2; i <= a3; a2 = i ){v5 = i;v6 = i[a1];if ( a2 < result && i < result ){do{if ( v6 > a1[result]){if ( i >= result )break;++i;a1[v5] = a1[result];if ( i >= result )break;while ( a1[i]<= v6 ){if ( ++i >= result )goto LABEL_13;}if ( i >= result )break;v5 =i;a1[result] = a1[i];}--result;}while ( i < result );}
LABEL_13:a1[result] = v6;sub_8210F0(a1, a2, i - 1);result = a3;++i;}return result;
}int main()
{char str[]="ZJSECaNH3ng"; sub_8210F0(str,0,10);printf("%s",str);return 0;
}
flag{UJWP1jMp}