乐固静态脱壳

其实在一月份的时候已经发在博客了,由于之前文章并不是MD格式,而博客几经折腾,所以之前的文章并没有放上来。

前记

最近看到很多人在研究腾讯乐固,试了下以前做的脱壳机,并且看了下最新版壳的实现,发现还是换汤不换药。测试了几个不同版本的样本,发现之前写的代码还能用,故此重新编辑。

方法

将dex文件放在同级目录下文件名改为classes.dex运行即可,在同级目录释放repair.dex即为修复dex,代码简陋难免有BUG,敬请谅解

原理

乐固其实只对Dex头大小为0xE0的位置进行了加密,且采用的xtea算法的变形,所以直接抠IDA F5之后解密的代码部分即可

源码:

#include "stdafx.h"
#include "windows.h"

char buf[0x10] = {0,};  
int DecodeDexHeader(int *a1, char *EncodeHeader, unsigned int len, int Key)  
{
    signed int v4; // r4@3
    unsigned int v5; // r5@3
    int v6; // r3@7
    int v7; // r7@7
    unsigned int v8; // r2@7
    unsigned int v9; // r3@7
    unsigned int i; // r4@7
    unsigned int v12; // [sp+0h] [bp-38h]@5
    unsigned int v13; // [sp+10h] [bp-28h]@5

    if (a1)
    {
        if (EncodeHeader)
        {
            v4 = 0;
            v5 = len & 7;
            if (!(len & 7))
            {
                v4 = 0;
                if (Key)
                {
                    v13 = len >> 3;
                    v12 = 0x9E3779B9 * Key;
                    while (v5 != v13)
                    {
                        v6 = 2 * (v5 & 1);
                        v7 = *((DWORD *)EncodeHeader + 1);
                        v8 = a1[v6] ^ *(DWORD *)EncodeHeader;
                        *(DWORD *)EncodeHeader = v8;
                        v9 = a1[v6 + 1] ^ v7;
                        *((DWORD *)EncodeHeader + 1) = v9;
                        for (i = v12; i; i += 0x61C88647)
                        {
                            v9 -= (i + v8) ^ (16 * v8 + a1[2]) ^ ((v8 >> 5) + a1[3]);
                            v8 -= (v9 + i) ^ (16 * v9 + *a1) ^ ((v9 >> 5) + a1[1]);
                        }
                        *(DWORD *)EncodeHeader = v8;
                        *((DWORD *)EncodeHeader + 1) = v9;
                        ++v5;
                        EncodeHeader += 8;
                    }
                    v4 = 1;
                }
            }
        }
        else
        {
            v4 = 0;
        }
    }
    else
    {
        v4 = 0;
    }
    return v4;
}

int GetDexDataOff(char* pDex)  
{
    return *(DWORD *)((DWORD)pDex + 0x6C);
}

int GetDexDataSize(char* pDex)  
{
    return *(DWORD *)((DWORD)pDex + 0x68);
}

int GetDexFileSize(char* pDex)  
{
    return *(DWORD *)((DWORD)pDex + 0x20);
}

int _tmain(int argc, _TCHAR* argv[])  
{
    HANDLE hTxDexFile = INVALID_HANDLE_VALUE;
    HANDLE hFixDexFile = INVALID_HANDLE_VALUE;

    DWORD dwTxDexFileSize;
    DWORD dwTxDexDataSize;
    DWORD dwTxDexDataOff;
    DWORD dwOrgDexFileSize;
    DWORD dwOrgDexOffinTxDex;
    DWORD dwRealWriteFileSize;

    char* pTxDex;
    char* pOrgDex;
    TCHAR* strDexPath = L"classes.dex";
    TCHAR* strRepairDexPath = L"repair.dex";

    hTxDexFile = CreateFile(strDexPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    hFixDexFile = CreateFile(strRepairDexPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hTxDexFile == INVALID_HANDLE_VALUE || hFixDexFile == INVALID_HANDLE_VALUE)
        return 0;

    LARGE_INTEGER FileSize = {};
    if (!GetFileSizeEx(hTxDexFile, &FileSize) || FileSize.QuadPart == 0)
        return 0;

    HANDLE hMap = CreateFileMapping(hTxDexFile, NULL, PAGE_READWRITE, 0, FileSize.QuadPart, NULL);
    if (hMap)
    {
        char *pMapBuffer = (char*)MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, FileSize.QuadPart);

        if (pMapBuffer)
        {
            dwTxDexFileSize = FileSize.QuadPart;
            pTxDex = (char*)malloc(dwTxDexFileSize);
            memset(pTxDex, 0, dwTxDexFileSize);
            memcpy(pTxDex, pMapBuffer, dwTxDexFileSize);

            dwTxDexDataSize = GetDexDataSize(pTxDex);
            dwTxDexDataOff = GetDexDataOff(pTxDex);

            dwOrgDexOffinTxDex = (dwTxDexDataSize + dwTxDexDataOff + 0x1000) >> 12 << 12;
            dwOrgDexFileSize = dwTxDexFileSize - dwOrgDexOffinTxDex;

            pOrgDex = (char*)malloc(dwOrgDexFileSize);
            memset(pOrgDex, 0, dwOrgDexFileSize);
            memcpy(pOrgDex, pTxDex + dwOrgDexOffinTxDex, dwOrgDexFileSize);


            if (DecodeDexHeader((int*)buf, pOrgDex, 0xE0, 0x20))
            {
                //这段其实之前是对文件大小校验了下,发现有一个样本好像并不相等,不知道是什么原因,如有所之,敬请告知,谢谢!
                //if (GetDexFileSize(pOrgDex) == dwOrgDexFileSize)
                //{
                    printf("Success");
                    WriteFile(hFixDexFile, pOrgDex, dwOrgDexFileSize, &dwRealWriteFileSize, 0);
                //}
            }

            UnmapViewOfFile(pMapBuffer);
        }
        CloseHandle(hMap);
    }
    CloseHandle(hFixDexFile);
    CloseHandle(hTxDexFile);



    return 0;
}
comments powered by Disqus