#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; } |