Siglus引擎 Unpack | 未完待续
前言
未完待续。
代码在这里:https://github.com/N0zoM1z0/SiglusEngine-Extract
以后随时会更新。()
因为我是选择直接逆向游戏引擎,在无源码,不hook的情况下硬逆Siglus……
路漫漫。。。
read.sav
可以直接逆SiglusCounter.exe
read.sav Unpack后可以得到游戏进度信息
# define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
char data[0x20000];
void sub_401000(BYTE* a1, BYTE* a2, int a3) {
BYTE* v3; // eax
unsigned int v4; // edx
BYTE* v5; // edi
BYTE* v6; // esi
int i; // ecx
unsigned int v10; // [esp+14h] [ebp+Ch]
v3 = a2;
v4 = *a1 + 256;
v5 = a1 + 1;
v10 = (unsigned int)&a2[a3]; // 末尾
if ((unsigned int)a2 < v10)
{
do
{
if (v4 == 1)
v4 = (unsigned __int8)*v5++ + 256;
if ((v4 & 1) != 0)
{
*v3++ = *v5++;
}
else
{
v6 = &v3[-(*(unsigned __int16*)v5 >> 4)];
for (i = (*(WORD*)v5 & 0xF) + 2; i > 0; --i)
*v3++ = *v6++;
v5 += 2;
}
v4 >>= 1;
} while ((unsigned int)v3 < v10);
}
}
int main() {
BYTE key[256] = { 0x8B, 0xE5, 0x5D, 0xC3, 0xA1, 0xE0, 0x30, 0x44, 0x00, 0x85, 0xC0, 0x74, 0x09, 0x5F, 0x5E, 0x33, 0xC0, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3, 0x8B, 0x45, 0x0C, 0x85, 0xC0, 0x75, 0x14, 0x8B, 0x55, 0xEC, 0x83, 0xC2, 0x20, 0x52, 0x6A, 0x00, 0xE8, 0xF5, 0x28, 0x01, 0x00, 0x83, 0xC4, 0x08, 0x89, 0x45, 0x0C, 0x8B, 0x45, 0xE4, 0x6A, 0x00, 0x6A, 0x00, 0x50, 0x53, 0xFF, 0x15, 0x34, 0xB1, 0x43, 0x00, 0x8B, 0x45, 0x10, 0x85, 0xC0, 0x74, 0x05, 0x8B, 0x4D, 0xEC, 0x89, 0x08, 0x8A, 0x45, 0xF0, 0x84, 0xC0, 0x75, 0x78, 0xA1, 0xE0, 0x30, 0x44, 0x00, 0x8B, 0x7D, 0xE8, 0x8B, 0x75, 0x0C, 0x85, 0xC0, 0x75, 0x44, 0x8B, 0x1D, 0xD0, 0xB0, 0x43, 0x00, 0x85, 0xFF, 0x76, 0x37, 0x81, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x6A, 0x00, 0x76, 0x43, 0x8B, 0x45, 0xF8, 0x8D, 0x55, 0xFC, 0x52, 0x68, 0x00, 0x00, 0x04, 0x00, 0x56, 0x50, 0xFF, 0x15, 0x2C, 0xB1, 0x43, 0x00, 0x6A, 0x05, 0xFF, 0xD3, 0xA1, 0xE0, 0x30, 0x44, 0x00, 0x81, 0xEF, 0x00, 0x00, 0x04, 0x00, 0x81, 0xC6, 0x00, 0x00, 0x04, 0x00, 0x85, 0xC0, 0x74, 0xC5, 0x8B, 0x5D, 0xF8, 0x53, 0xE8, 0xF4, 0xFB, 0xFF, 0xFF, 0x8B, 0x45, 0x0C, 0x83, 0xC4, 0x04, 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3, 0x8B, 0x55, 0xF8, 0x8D, 0x4D, 0xFC, 0x51, 0x57, 0x56, 0x52, 0xFF, 0x15, 0x2C, 0xB1, 0x43, 0x00, 0xEB, 0xD8, 0x8B, 0x45, 0xE8, 0x83, 0xC0, 0x20, 0x50, 0x6A, 0x00, 0xE8, 0x47, 0x28, 0x01, 0x00, 0x8B, 0x7D, 0xE8, 0x89, 0x45, 0xF4, 0x8B, 0xF0, 0xA1, 0xE0, 0x30, 0x44, 0x00, 0x83, 0xC4, 0x08, 0x85, 0xC0, 0x75, 0x56, 0x8B, 0x1D, 0xD0, 0xB0, 0x43, 0x00, 0x85, 0xFF, 0x76, 0x49, 0x81, 0xFF, 0x00, 0x00, 0x04, 0x00, 0x6A, 0x00, 0x76 };
FILE* in;
in = fopen("D:\\N0zoM1z0\\Sec-Learning\\Reverse\\游戏逆向\\read.sav", "rb");
fread(data, sizeof(char), sizeof(data), in);
DWORD* dw_data = (DWORD*)data;
DWORD v12 = dw_data[2];
DWORD v26 = dw_data[3];
for (int i = 0x10; i < 0x10 + v12; i++) {
data[i] ^= key[(i - 0x10) & 0xFF];
}
DWORD v25 = dw_data[5];
void* Block = malloc(v25);
sub_401000((BYTE*)data + 24, (BYTE*)Block, v25);
printf("+++++++++++++++++++++++++++++++++++++++++++++++");
for (int i = 0; i < v25; i++) {
BYTE c = *((BYTE*)Block + i);
} // checked ✔️
FILE* Stream = fopen("D:\\N0zoM1z0\\Sec-Learning\\Reverse\\游戏逆向\\SiglusCounter.txt", "wb");
FILE* v4; // eax
FILE* v5; // edi
char* v6; // eax
const char* v7; // edi
char* v8; // eax
FILE* v9; // eax
FILE* v10; // edi
void* v11; // esi
int* v13; // esi
const WCHAR* v14; // esi
int* v15; // esi
int v16; // ecx
size_t v17; // eax
int v19; // [esp-14h] [ebp-3A0h]
char Buffer[304]; // [esp+Ch] [ebp-380h] BYREF
CHAR MultiByteStr[260]; // [esp+13Ch] [ebp-250h] BYREF
CHAR pszPath[304]; // [esp+240h] [ebp-14Ch] BYREF
int v24; // [esp+374h] [ebp-18h]
size_t v27; // [esp+380h] [ebp-Ch]
size_t Size; // [esp+384h] [ebp-8h]
if (Stream)
{
v13 = (int*)Block;
v24 = 0;
Size = 0;
if (v26 > 0)
{
v25 = v26;
do
{
v19 = *v13;
v14 = (const WCHAR*)(v13 + 1);
v26 = v19;
MultiByteStr[WideCharToMultiByte(0x3A4u, 0, v14, v19, MultiByteStr, 256, 0, 0)] = 0;
v15 = (int*)&v14[v26];
v16 = *v15;
v13 = v15 + 1;
v26 = v16;
if (v16)
{
v17 = 0;
v27 = 0;
if (v16 > 0)
{
v27 = v16;
do
{
v17 += *(unsigned __int8*)v13;
v13 = (int*)((char*)v13 + 1);
--v27;
} while (v27);
v27 = v17;
}
Size += v17;
v24 += v16;
fprintf(
Stream,
"%6d/%6d %3d.%d%% %s\r\n",
v27,
v26,
(int)(1000 * v17) / v16 / 10,
(int)(1000 * v17) / v16 % 10,
MultiByteStr);
}
--v25;
} while (v25);
}
free(Block);
fprintf(
Stream,
"----------------------------------------\r\n%6d/%6d %3d.%d%% (ALL)\r\n",
Size,
v24,
(int)(1000 * Size) / v24 / 10,
(int)(1000 * Size) / v24 % 10);
fclose(Stream);
}
ShellExecuteA(0, "open", "D:\\N0zoM1z0\\Sec-Learning\\Reverse\\游戏逆向\\SiglusCounter.txt", NULL,NULL, 1);
}
mode.cgm
这个解出来是一个TABLE,感觉像是来索引各个g00图片文件的。
解出来大概长这样:
nwa
网上有现成脚本,就不自己造轮子了。
https://github.com/mirrorange/NwaConverter
强烈建议解Rewrite的BGM017
,散花!(sakuya😭)
g00
逆了好久。。。还只弄了一个分支。。。
占个坑,后面补完整。
终于可以解出Rewrite的CG了😭😭😭
# define _CRT_SECURE_NO_WARNINGS
#include<Windows.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdint.h>
using namespace std;
void Unpack_1(UINT8 a1,BYTE* a2,BYTE* a3,DWORD fileLen) {
}
int Unpack_2(UINT8 a1, BYTE* a2, BYTE* a3,DWORD fileLen) {
/*
*/
int result; // eax
char v4; // cf
char v5; // cl
int v6; // esi
BYTE* v7; // esi
BYTE* v8; // edi
BYTE* v9; // [esp-4h] [ebp-4h]
DWORD cnt = 0;
DWORD id1 = 0, id2 = 0; // id1: edi id2:esi
fileLen -= 0xD;
DWORD flag = 0;
while (TRUE) {
if (!flag) {
a1 = a3[id2];
++id2;
flag = 7;
}
else {
flag--;
}
if (id2 >= fileLen)break;
if(id1 == 0x10038)
printf("[+] a1: %x id1: %x\n", a1,id1);
v4 = a1 & 1;
a1 >>= 1;
if (v4) {
//
for (int i = 0; i < 3; i++) {
a2[id1 + i] = a3[id2 + i];
}
a2[id1 + 3] = 0;
id1 += 4;
id2 += 3;
} // checked
else {
int WORD_a3 = *(WORD*)((BYTE*)a3 + id2);
v5 = (WORD_a3 & 0xF) + 1;
v6 = (id1 - (4 * (WORD_a3 >> 4))); // !!! 这里不能用WORD!!! ... 要int 。。。
//cnt += 1;
//printf("v6: %x id1: %x\n", v6,id1);
//if (cnt > 3)return;
//return;
do {
for (int i = 0; i < 4; i++) {
a2[id1 + i] = a2[v6 + i];
}
id1 += 4;
v6 += 4;
v5--;
} while (v5);
id2 += 2;
}
}
return id1; // .... 开始手贱写成id2了...
}
DWORD dword_404337, dword_404333, dword_40433F, dword_404343;
void Trans2BMP_1() {
}
int Trans2BMP_2(LPCVOID dword_40434B,LPCVOID lpBuffer) {
int v2; // ebx
int v3; // edi
__int16 v4; // cx
__int16 v5; // cx
__int16 v6; // ax
__int16 v7; // dx
int result; // eax
int v9; // [esp-6h] [ebp-6h]
__int16 v10; // [esp-2h] [ebp-2h]
BYTE* v0 = (BYTE*)dword_40434B;
BYTE* v1 = (BYTE*)lpBuffer;
*(WORD*)lpBuffer = 0x4D42;
*(DWORD*)(v1 + 2) = dword_404343 + 54;
*(DWORD*)(v1 + 6) = 0;
*(DWORD*)(v1 + 10) = 54;
*(DWORD*)(v1 + 14) = 40;
v2 = dword_404337;
*(DWORD*)(v1 + 18) = dword_404333;
*(DWORD*)(v1 + 22) = v2;
*((WORD*)v1 + 13) = 1;
*((WORD*)v1 + 14) = 24;
*(DWORD*)(v1 + 30) = 0;
*(DWORD*)(v1 + 34) = 0;
*(DWORD*)(v1 + 38) = 0;
*(DWORD*)(v1 + 42) = 0;
*(DWORD*)(v1 + 46) = 0;
*(DWORD*)(v1 + 50) = 0;
v3 = (v2 - 1) * dword_40433F + 54;
v4 = dword_404337;
int idx_0 = 0;
do {
v10 = v4;
v9 = v3;
v5 = dword_404333;
do {
/*printf("v3: %x\n", v3);
return 1;*/
v1[v3] = v0[idx_0];
v1[v3 + 1] = v0[idx_0 + 1];
v1[v3 + 2] = v0[idx_0 + 2];
idx_0 += 4;
v3 += 3;
--v5;
} while (v5);
v3 = v9 - dword_40433F;
//if (v3 == 0x36)break;
v4 = v10 - 1;
} while (v10 != 1);
result = dword_404337 * dword_40433F + 54;
return result;
}
void Unpack_G00(const CHAR* FileName) {
HANDLE hFile = CreateFileA(FileName, GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile == INVALID_HANDLE_VALUE) {
printf("[-] Error in CreateFileA!\n");
return;
}
DWORD dwFileSize = GetFileSize(hFile, NULL);
BYTE* buffer = (BYTE*)malloc(dwFileSize*2);
ZeroMemory(buffer, dwFileSize);
DWORD dwBytesToRead = dwFileSize;
ReadFile(hFile, buffer, dwBytesToRead, &dwBytesToRead, NULL);
printf("[+] BytesRead: %x\n", dwBytesToRead);
LPCVOID lpBuffer = buffer;
if (!(*(BYTE*)lpBuffer)) {
DWORD fileLen;
fileLen = *(DWORD*)((BYTE*)lpBuffer + 5) + 5;
printf("[+] fileLen: %x\n", fileLen);
BYTE* newBuf = (BYTE*)malloc(fileLen*2);
DWORD dwUnpackSize = Unpack_2(*((BYTE*)lpBuffer + 0xD), newBuf, (BYTE*)((BYTE*)(lpBuffer) + 0xD), fileLen);
FILE* out = fopen("D:\\N0zoM1z0\\Sec-Learning\\Reverse\\游戏逆向\\EXP\\g00cnv1\\etract", "wb");
fwrite(newBuf, sizeof(BYTE), dwUnpackSize, out);
printf("[+] Unpack Done!\n");
// 9310000
dword_404337 = *(unsigned __int16*)((char*)lpBuffer + 3);
dword_404333 = *(unsigned __int16*)((char*)lpBuffer + 1);
dword_40433F = (3 * dword_404333 + 3) & 0xFFFFFFFC;
dword_404343 = dword_404337 * dword_40433F;
LPCVOID pBMPBuffer = (BYTE*)malloc((16 * dword_404337 * dword_40433F + 54) + 1);
DWORD dw_bmpSize = Trans2BMP_2(newBuf, pBMPBuffer);
out = fopen("D:\\N0zoM1z0\\Sec-Learning\\Reverse\\游戏逆向\\EXP\\g00cnv1\\extract.bmp", "wb");
fwrite(pBMPBuffer, sizeof(BYTE), dw_bmpSize, out);
printf("[+] Transfer to BMP file done!\n");
}
else {
}
}
int main() {
Unpack_G00("D:\\N0zoM1z0\\Sec-Learning\\Reverse\\游戏逆向\\Rewrite\\g00\\FGSZ08.g00");
}
强烈吐槽IDA!!!
这个v6,IDA识别的是WORD类型,也就是无符号,但是,调试了好久,才发现要用有符号。。。这就是最开始extract半天没对的地方!。。