sun博客

记录点滴!

//第一种
unsigned char spAdd8[4];
       numberToByteArray(SP+8,spAdd8,4);
        printBytes(spAdd8,4);
        // uc_mem_write(uc,base+0x26BBC, spAdd8,4);
       uc_mem_write(uc,base+0x26BBC,"\x08\xfc\xef\x40",4);
       uc_mem_write(uc,SP+8,"\x00\x00\x00\x00",4);
       printf("fdsfds\n");
        unsigned char spAdd8[4];
        uint64_t ox=0x50000000;
        uc_mem_map(uc,ox,0x1000,UC_PROT_ALL);//分配内存最小值0x1000
        numberToByteArray(ox,spAdd8,4);
        printBytes(spAdd8,4);
        uc_mem_write(uc,base+0x26BBC, spAdd8,4);
        uc_mem_write(uc,ox,"\x00",1);
        printf("fdsfds\n");

注意经测试uc_mem_map分配size小于0x1000,会导致报错。另外在arm指令中,如ldr r0,[r0]中,其读取的内存区间一定要在分配的内存中,不然会报unmap的错。

//第一种
unsigned char spAdd8[4];
       numberToByteArray(SP+8,spAdd8,4);
        printBytes(spAdd8,4);
        // uc_mem_write(uc,base+0x26BBC, spAdd8,4);
       uc_mem_write(uc,base+0x26BBC,"\x08\xfc\xef\x40",4);
       uc_mem_write(uc,SP+8,"\x00\x00\x00\x00",4);
       printf("fdsfds\n");
        unsigned char spAdd8[4];
        uint64_t ox=0x50000000;
        uc_mem_map(uc,ox,0x1000,UC_PROT_ALL);//分配内存最小值0x1000
        numberToByteArray(ox,spAdd8,4);
        printBytes(spAdd8,4);
        uc_mem_write(uc,base+0x26BBC, spAdd8,4);
        uc_mem_write(uc,ox,"\x00",1);
        printf("fdsfds\n");

以下是最为重要的一种。必须牢牢掌握。

//第三种:        
        uint32_t re=0;
        uint32_t* ptrRe=&re;//把64位的指针转换成32位的
        printf("ptrRe:0x%x\n", ptrRe);
        uintptr_t address= reinterpret_cast<uintptr_t>(ptrRe);//把指针转成数字
        printf("address,%x\n",address);

        printf("address2,%x\n",address&0xfffff000);//后三数清0


        unsigned char bytearr[4];
        numberToByteArray(address,bytearr,4);
        uc_mem_map(uc, address&0xfffff000, 0x10000, UC_PROT_ALL);//base的最后三位也要为0,arm中只能是4个字节,多于4个字节会超过寻址能力,分配内存最小值0x1000
        uc_mem_write(uc,base+0x26BBC, bytearr,4);//这里就能二级指针映射到re的值0呢

注意经测试uc_mem_map分配size小于0x1000,会导致报错。另外在arm指令中,如ldr r0,[r0]中,其读取的内存区间一定要在分配的内存中,不然会报unmap的错。

以下为整个页面源代码:

//test.cpp
// Created by cxl on 10/8/23.
//
//
// Created by cxl on 2023-10-05.
//
#include <iostream>
#include <fstream>
#include <cstring>
#include <vector>
#include <iomanip>
#include "unicorn/unicorn.h"
#include "capstone/capstone.h"
#include "utils.h"


static csh handle;
using namespace std;

long getfilelength(FILE *fp)
{
    long curpos=0L;
    long length=0L;
    curpos = ftell(fp);
    fseek(fp, 0L, SEEK_END);
    length = ftell(fp);
    fseek(fp, curpos, SEEK_SET);
    return length;
}

string trans(string s){
    std::ifstream file(s, std::ios::binary);
    if (!file.is_open()) {
        std::cerr << "Failed to open file." << std::endl;
        return "fail";
    }

    std::stringstream ss;
    ss << std::hex << std::uppercase << std::setfill('0');

    char c;
    while (file.get(c)) {
        ss << std::setw(2) << static_cast<unsigned int>(static_cast<unsigned char>(c));
    }

    std::string hexString = ss.str();
    std::cout << hexString << std::endl;
    return hexString;
}


void hook_code(uc_engine *uc, uint64_t address, uint32_t size,void *user_data){
    cs_insn *insn;
    unsigned char* code=new unsigned char[size];
    uc_mem_read(uc,address,code,size);
    //printBytes(code,size);
    size_t count=cs_disasm(handle,code,size,0,0,&insn);
    if(address==0x400115ec){
        int re;
        uc_reg_read(uc,UC_ARM_REG_R0,&re);
        printf("0x400115ec,r0 result Is %x\n",re);

    }
    if(address==0x400115ee){
        printf("enter...\n");
        int re;
        uc_reg_read(uc,UC_ARM_REG_R0,&re);
        printf("0x400115ee,r0 result Is %x\n",re);

    }
    if(address==0x4001160a){
        printf("enter...\n");
        int re;
        uc_reg_read(uc,UC_ARM_REG_R0,&re);
        printf("0x4001160a,r0 result Is %d\n",re);

    }

    if(count){
        for (int i = 0; i < count; ++i) {
            printf("count %d   0x%" PRIx64 ":\t%s\t%s\n", count,address, insn[i].mnemonic, insn[i].op_str);
        }
    }else{
        printf("count value is 0");
    }

}
int main(){
    try{
        uint64_t start_addr=0x115E0;
        uint64_t end_addr=0x1160C;
        uint64_t base=0x40000000;
        uint64_t base_offset=0x00F00000;//10M
        uint64_t r0=1;
        uint64_t r1=2;
        uint64_t SP=base+base_offset-0x400;
        uint64_t lR=base+0x234;
        uc_hook trace;
        uc_engine* uc;

        uc_err err=uc_open(UC_ARCH_ARM,UC_MODE_THUMB,&uc);
        cs_err csErr=cs_open(CS_ARCH_ARM,CS_MODE_THUMB,&handle);
        if (err != UC_ERR_OK) {
            printf("Failed on uc_mem_map() with error returned: %u\n", err);
        }
        if (csErr) {
            printf("Failed on cs_open() with error returned: %u\n", err);
            abort();
        }
        size_t fileSize=0;
        unsigned char* bytearray=readFileToByteArray("../bin/libnative-lib.so",fileSize);
        // cout<<setw(2)<<hex<<uppercase<<setfill('0')<<static_cast<int>(bytearray[fileSize-8])<<endl;
        //printBytes(bytearray, fileSize);

        cs_insn *insn;
        //unsigned char block[]={0x80,0xb5,0x6F,0x46};

        unsigned char* block=arraySlice(bytearray,start_addr,end_addr);
        size_t count=cs_disasm(handle,block,end_addr-start_addr,0,20,&insn);
        // size_t count=cs_disasm(handle,(unsigned char *)THUMB_CODE,sizeof(THUMB_CODE) - 1,0x80001000,0,&insn);
        cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
        if(count){
            for (int i = 0; i < count; ++i) {
                printf("0x%" PRIx64 ":\t%s\t%s\n", insn[i].address, insn[i].mnemonic, insn[i].op_str);
                //  print_insn_detail(handle,&insn[i]);
            }
        }else{
            printf("ERROR: Failed to disasm given code!\n");
        }
        printf("capstone end.....\n");


        uc_mem_map(uc,base,base_offset,UC_PROT_ALL);
        uc_mem_write(uc,base,bytearray,fileSize);
        //string s=trans("../bin/libnative-lib.so");

        //uc_mem_write(uc,base,s.c_str(),s.length());

        uc_reg_write(uc,UC_ARM_REG_R0, &r0);
        uc_reg_write(uc,UC_ARM_REG_R1,&r1);
        uc_reg_write(uc,UC_ARM_REG_SP,&SP);
        uc_reg_write(uc,UC_ARM_REG_LR,&lR);

        uint32_t re=0;
        uint32_t* ptrRe=&re;//把64位的指针转换成32位的
        printf("ptrRe:0x%x\n", ptrRe);
        uintptr_t address= reinterpret_cast<uintptr_t>(ptrRe);//把指针转成数字
        printf("address,%x\n",address);

        printf("address2,%x\n",address&0xfffff000);//后三数清0


        unsigned char bytearr[4];
        numberToByteArray(address,bytearr,4);
        uc_mem_map(uc, address&0xfffff000, 0x10000, UC_PROT_ALL);//base的最后三位也要为0,arm中只能是4个字节,多于4个字节会超过寻址能力,分配内存最小值0x1000
        uc_mem_write(uc,base+0x26BBC, bytearr,4);//这里就能二级指针映射到re的值0呢
        //uc_mem_write(uc,address,"\x00",1);


        uc_hook_add(uc, &trace, UC_HOOK_CODE, reinterpret_cast<void*>(hook_code), NULL, 1, 0);
        uc_emu_start(uc,base+start_addr+1,base+end_addr,0,0);


        uint64_t r0_result;
        uc_reg_read(uc,UC_ARM_REG_R0,&r0_result);
        printf("r0 xxis: %d\n",r0_result);//输出3,结果正确。
        delete[] bytearray;
    } catch (exception variable) {
        cout<<"err"<<endl;
    }


}

注意经测试uc_mem_map分配size小于0x1000,会导致报错。另外在arm指令中,如ldr r0,[r0]中,其读取的内存区间一定要在分配的内存中,不然会报unmap的错。

发表评论

邮箱地址不会被公开。 必填项已用*标注