Cortex-M0 代碼解析——02代碼解壓縮

1. 分析流程介紹

經過分析,代碼中有一段是經過壓縮的,具體的算法我沒有詳細研究,但是對於應用至上的我而言,暫時沒有看懂是無關緊要的,關鍵是能不能靈活應用。

下圖是之前分析的相關地址和對應的參數。

 

簡單描述一下:

在原始文件中,明顯的數據量不夠,通過IDA進行分析,將解壓縮的方式通過類C的代碼,給分析出來。此時我採用的方式爲,先通過計算的方式,將我所需要解壓縮的代碼單獨提取出來,然後通過剛剛得到的解壓縮代碼,進行解壓縮處理,從而得到最終的結果。

2. 分析結果

還記得上一篇文章中說明的BaseTable相關參數的含義嗎(忘記的可以去查閱),從上圖中就能找到_copy_and_unzip的地址(當然了,名字是我自己起的,用於表示解壓縮並數據搬移的函數,後續均採用該函數名),也即0x132E。分析後的代碼如下:

int __cdecl _copy_and_unzip(int *rom_addr, int *ram_addr, unsigned int size)

{
  int *v3; // r4
  int v4; // r5
  int v5; // r3
  int v6; // r2
  char v7; // r6
  int v8; // r3
  _BYTE *v9; // r3
  int v10; // r2

  v3 = (ram_addr + size);
  do
  {
    v4 = *rom_addr;
    rom_addr = (rom_addr + 1);
    v5 = v4 & 7;
    if ( !(v4 & 7) )
    {
      v5 = *rom_addr;
      rom_addr = (rom_addr + 1);
    }

    v6 = v4 >> 4;
    if ( !(v4 >> 4) )
    {
      v6 = *rom_addr;
      rom_addr = (rom_addr + 1);
    }

    while ( --v5 )
    {
      v7 = *rom_addr;
      rom_addr = (rom_addr + 1);
      *ram_addr = v7;
      ram_addr = (ram_addr + 1);
    }

    if ( v4 & 8 )
    {
      v8 = *rom_addr;
      rom_addr = (rom_addr + 1);
      v9 = ram_addr - v8;
      v10 = v6 + 2;

      while ( --v10 >= 0 )
      {
        *ram_addr = *v9;
        ram_addr = (ram_addr + 1);
        ++v9;
      }
    }
    else
    {
      while ( --v6 >= 0 )
      {
        *ram_addr = 0;
        ram_addr = (ram_addr + 1);
      }
    }
  }

  while ( ram_addr < v3 );

  return 0;
}

從bin文件中將0x3814到bin最後的數據全部提取出來(可以考慮使用winhex工具,該工具方法見我的另一篇文章),保存爲C語言數組形式,隨後在VS2019中使用上述的解壓縮代碼和剛剛提取出來的數據,進行解壓。算了,我將我寫的簡單測試函數也貼在這裏吧,方便後續直接使用。

#include <stdint.h>
#include <stdio.h>

extern uint8_t data[540];
extern int __fastcall _copy_and_unzip(uint8_t* a1, uint8_t* a2, int a3);

// 這個0x358是從源碼中看出來的。
#define DATA_UNZIP_SIZE			0x358
uint8_t data_unzip[DATA_UNZIP_SIZE];

void display_hex(uint8_t* data, uint32_t len)
{
	for (uint32_t i = 0; i < len; i++)
	{
		printf("%02x ", *(data + i));
	}
	printf("\n");
}

void main(void)
{
	display_hex(data, sizeof(data));
	printf("------------------------------------\n");
	_copy_and_unzip(data, data_unzip, DATA_UNZIP_SIZE);
	display_hex(data_unzip, DATA_UNZIP_SIZE);
}

大致的結果如下,因某些數據涉密,就打碼了。

隨後,將得到的最終結果,覆蓋掉原始bin文件中最後的未解壓部分(當然了,最後覆蓋前先備份一下)。覆蓋二進制文件,可以使用winhex,特別好用的一個工具。然後就可以開開心心的進行代碼分析了。哈哈,本章結束。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章