当前位置: 首页 > article >正文

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半天没对的地方!。。


http://www.kler.cn/a/400771.html

相关文章:

  • 计算机网络-MSTP基础实验一(单域多实例)
  • 智谱AI清影升级:引领AI视频进入音效新时代
  • 解决 Spring Boot 中 `Ambiguous mapping. Cannot map ‘xxxController‘ method` 错误
  • 搭建MC服务器
  • Android 使用Retrofit 以纯二进制文件流上传文件
  • .NET 简介
  • 单用户模式下执行passwd root ,返回的是(current) UNIX passwd
  • WPF命令
  • OAI-5G开源通信平台实践(二)
  • 【数据结构】【线性表】静态链表(附C语言源码)
  • 多模态基础模型:从专家到通用助手
  • 【后端】版本控制
  • 特权帐户安全 CyberArk
  • 开源财富管理软件Ghostfolio的安装
  • el-table中增加校验方法(二)
  • JavaScript 原型
  • golang通用后台管理系统09(系统操作日志记录)
  • MySQL —— MySQL索引介绍、索引数据结构、聚集索引和辅助索引、索引覆盖
  • C#.Net筑基-模式匹配汇总
  • 剧本杀门店预约小程序,解锁沉浸式推理体验
  • 热点更新场景,OceanBase如何实现性能优化
  • Debezium-EmbeddedEngine
  • 基于云计算的文件存储与共享平台开发
  • 创新实践:基于边缘智能+扣子的智能轮椅 AIoT 解决方案
  • CSDN如何写出”爆款“文章
  • 计算机视觉在自动驾驶汽车中的应用