#include "stdafx.h"
#include <inttypes.h>
#include <string.h>
#include <math.h>
#include <unicorn/unicorn.h>
#pragma comment(lib,"unicorn.lib")
//#define DEBUG
#define _DWORD uint32_t
#define LODWORD(x) (*((_DWORD*)&(x)))
#define HIDWORD(x) (*((_DWORD*)&(x)+1))
#define ADDRESS 0x249BC8
#define BASE 0xaef52000
#define CODE_SIZE 8*1024*1024
#define STACK_ADDR BASE+CODE_SIZE
#define STACK_SIZE 1024 * 1024
#define PARAM_ADDR STACK_ADDR+STACK_SIZE
#define PARAM_SIZE 1024 * 1024
uint32_t offset=0;
static uint32_t create_mem(uc_engine *uc,char* buffer,uint32_t len)
{
uint32_t addr = PARAM_ADDR + offset;
uc_mem_write(uc, addr, buffer, len);
offset += len + 1;
return addr;
}
static void print_reg(uc_engine *uc, uint32_t address)
{
#ifdef DEBUG
uint32_t pc = 0;
uc_reg_read(uc, UC_ARM_REG_PC, &pc);
if (pc == address)
{
printf("========================\n"); printf("Break on 0x%x\n", pc);
uint32_t values = 0;
uc_reg_read(uc, UC_ARM_REG_R0, &values); printf("R0 = 0x%x \n", values);
uc_reg_read(uc, UC_ARM_REG_R1, &values); printf("R1 = 0x%x \n", values);
uc_reg_read(uc, UC_ARM_REG_R2, &values); printf("R2 = 0x%x \n", values);
uc_reg_read(uc, UC_ARM_REG_R3, &values); printf("R3 = 0x%x \n", values);
uc_reg_read(uc, UC_ARM_REG_R4, &values); printf("R4 = 0x%x \n", values);
uc_reg_read(uc, UC_ARM_REG_R5, &values); printf("R5 = 0x%x \n", values);
uc_reg_read(uc, UC_ARM_REG_R6, &values); printf("R6 = 0x%x \n", values);
uc_reg_read(uc, UC_ARM_REG_PC, &values); printf("PC = 0x%x \n", values);
uc_reg_read(uc, UC_ARM_REG_SP, &values); printf("SP = 0x%x \n", values);
printf("========================\n");
}
#endif // DEBUG
}
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
{
#ifdef DEBUG
printf(">>> Tracing instruction at 0x%" PRIx64 ", instruction size = 0x%x\n", address, size);
#endif // DEBUG
switch (address)
{
//strlen
case BASE + 0x249BEE:
{
uint32_t r0 = 0;
char buffer[4096] = "";
uc_reg_read(uc, UC_ARM_REG_R0, &r0);
uc_mem_read(uc, r0, buffer, 4096);
r0 = strlen(buffer);
uc_reg_write(uc, UC_ARM_REG_R0, &r0);
uint32_t pc = address;
pc += 5;
uc_reg_write(uc, UC_ARM_REG_PC, &pc);
break;
}
//malloc
case BASE+ 0x249f3c:
case BASE+ 0x249f06:
case BASE + 0x249c02:
{
uint32_t r0 = 0;
uc_reg_read(uc, UC_ARM_REG_R0, &r0);
char* buffer = (char*)malloc(r0);
r0=create_mem(uc, buffer, r0);
free(buffer);
uc_reg_write(uc, UC_ARM_REG_R0, &r0);
uint32_t pc = address;
pc += 5;
uc_reg_write(uc, UC_ARM_REG_PC, &pc);
break;
}
//memcpy 后为THUMB指令
case BASE+0x249c68:
case BASE+0x249c0e:
case BASE+0x24947A:
case BASE+0x249456:
{
uint32_t r0 = 0;
uint32_t r1 = 0;
uint32_t r2 = 0;
uc_reg_read(uc, UC_ARM_REG_R0, &r0);
uc_reg_read(uc, UC_ARM_REG_R1, &r1);
uc_reg_read(uc, UC_ARM_REG_R2, &r2);
char *buffer =(char*)malloc(r2);
uc_mem_read(uc, r1, buffer, r2);
uc_mem_write(uc, r0, buffer, r2);
free(buffer);
uint32_t pc = address;
//memcpy 后为ARM指令
if (address == BASE + 0x249c68)
pc += 4;
else
pc += 5;
uc_reg_write(uc, UC_ARM_REG_PC, &pc);
break;
}
//特殊处理4字ARM指令
case BASE + 0x249C6C:
{
uint32_t pc = address;
pc += 5;
uint32_t r0 = 0x2c0;
uc_reg_write(uc, UC_ARM_REG_R0, &r0);
uc_reg_write(uc, UC_ARM_REG_PC, &pc);
break;
}
//跳过stack_guard错误的内存地址
case BASE + 0x249BD8:
{
uint32_t pc = address;
pc += 7;
uc_reg_write(uc, UC_ARM_REG_PC, &pc);
break;
}
//sin函数
case BASE+0x249EE8:
{
uint32_t r0 = 0;
uint32_t r1 = 0;
uc_reg_read(uc, UC_ARM_REG_R0, &r0);
uc_reg_read(uc, UC_ARM_REG_R1, &r1);
double value = 0;
memcpy(&value, &r0, 4);
memcpy((char*)&value+4, &r1, 4);
double ret=sin(value);
r0 = LODWORD(ret);
r1 = HIDWORD(ret);
uc_reg_write(uc, UC_ARM_REG_R0, &r0);
uc_reg_write(uc, UC_ARM_REG_R1, &r1);
uint32_t pc = address;
pc += 5;
uc_reg_write(uc, UC_ARM_REG_PC, &pc);
break;
}
//free
case BASE+ 0x24a68c:
case BASE+0x249f24:
{
uint32_t pc = address;
pc += 5;
uc_reg_write(uc, UC_ARM_REG_PC, &pc);
}
default:
{
print_reg(uc, address);
break;
}
}
}
static unsigned char* read_file(char* path, uint32_t* len)
{
FILE* fp = fopen(path, "rb");
if (fp == NULL)
return nullptr;
fseek(fp, 0, SEEK_END);
*len = ftell(fp);
fseek(fp, 0, SEEK_SET);
unsigned char* code = (unsigned char*)malloc(*len);
memset(code, 0, *len);
fread(code, 1, *len, fp);
fclose(fp);
return code;
}
static void test_thumb(void)
{
uc_engine *uc;
uc_err err;
uc_hook trace1, trace2;
uint32_t sp = STACK_ADDR;
offset = 0;
err = uc_open(UC_ARCH_ARM, UC_MODE_THUMB, &uc);
if (err) {
printf("Failed on uc_open() with error returned: %u (%s)\n",
err, uc_strerror(err));
return;
}
char plain[] = "/vps?tvid=11949478009&vid=7b23569cbed511dd58bcd6ce9ddd7b42&v=0&qypid=11949478009_unknown&src=02022001010000000000&tm=1519712402&k_tag=1&k_uid=359125052784388&bid=1&pt=0&d=1&s=0&rs=1&dfp=1413357b5efa4a4130b327995c377ebb38fbd916698ed95a28f56939e9d8825592&k_ver=9.0.0&k_ft1=859834543&k_err_retries=0&qd_v=1";
uc_mem_map(uc, PARAM_ADDR, PARAM_SIZE, UC_PROT_ALL);
uc_mem_map(uc, BASE, CODE_SIZE, UC_PROT_ALL);
uint32_t r0 = PARAM_ADDR;
uint32_t sp_start = sp + STACK_SIZE;
int ret=uc_mem_map(uc, sp, sp_start - sp, UC_PROT_ALL);
uint32_t len = 0;
unsigned char* code = read_file("./aef52000_36e000.so", &len);
uc_mem_write(uc, BASE, code, len);
free(code);
create_mem(uc, plain, strlen(plain) + 1);
uc_reg_write(uc, UC_ARM_REG_R0, &r0);
uc_reg_write(uc, UC_ARM_REG_SP, &sp);
uc_hook_add(uc, &trace2, UC_HOOK_CODE, hook_code, NULL, 1, 0);
err = uc_emu_start(uc, BASE + 0x249BC8 + 1, BASE + 0x24a692, 0, 0);
if (err) {
printf("Failed on uc_emu_start() with error returned: %u\n", err);
}
char buffer[4096] = "";
uc_reg_read(uc, UC_ARM_REG_R0, &r0);
uc_mem_read(uc, r0, buffer, 4096);
printf("result:%s\n", buffer);
uc_close(uc);
}
int main()
{
test_thumb();
system("pause");
return 0;
}