当前位置:网站首页>Risc-v Process Attack
Risc-v Process Attack
2022-08-01 19:01:00 【修川地藏。】
目录
一、 Overview
In the previous article, I introduced how to build the risc-v Linux kernel GDB debug environment. This article mainly introduces how to dump the memory of the risc-v process and how to simulate the execution of the process.
First of all, I need to say that because my original development environment is windows, I use the versions of Unicorn and capstone that are both in Windows environment. Later, I will introduce how to use these two frameworks.
二、Tools
Qemu
riscv64-unknown-elf-gdb
Visual stdio 2019
三、Memory dump
1. First, write a very simple verification process. Judge whether the input is a string of numbers. If the input is correct, it returns right, and if the input is wrong, it returns fault.
#include <stdio.h>
#include <stdlib.h>
#define FALSE 0
#define TRUE 1
char str[1024] = { 0 };
int mystrcmp(char* p1, char* p2)
{
while (*p1 & *p2)
{
if (*p1 != *p2)
return FALSE;
p1++;
p2++;
if (*p1 || *p2)
return FALSE;
}
return TRUE;
}
int main(void)
{
int a = 0;
while(1)
{
scanf("%s", str);
if (mystrcmp(str, (char*)"13755891234"))
printf("Right!\n");
else
printf("Fault!Try again\n");
}
return 0;
}
2. Compile the .c file using riscv64-unknown-elf-gcc or riscv64-linux-gnu-gcc.
3. The generated file is copied into busybox/_install/dev directory, and then create the image of the file system.
find -print0 | cpio -0oH newc | gzip -9 > ../rootfs.img
Then use QEMU to run the Linux kernel in debug mode. The command line is as follows:
qemu-system-riscv64 \
-nographic -machine virt \
-bios /home/bdai/yulong/risc-v/opensbi/build/platform/generic/firmware/fw_dynamic.bin \
-kernel /home/bdai/yulong/risc-v/linux-5.9/arch/riscv/boot/Image \
-initrd /home/bdai/yulong/risc-v/busybox-1.35.0/rootfs.img \
-append "root=/dev/ram rdinit=/sbin/init" \
-S \
-s
Start another terminal, execute riscv64-unknown-elf-gdb vmlinux -ex 'target remote localhost:1234' under the directory including vmlinux, and then execute continue.
3、Open a new terminal and disassemble the process with riscv64-unknown-elf-objdump. We can see in the disassembly file that the addresses of main and puts functions are 0x10156, 0x1018a and 0x10198 respectively.
4、Then we need to find the entry point of the program. The address of the entry point is 0x10156. At the same time, we also set a breakpoint at the address of the puts function of the process. If only at the entry point of the main function, memory such as stack segment and heap segment has not been allocated, so we set a hardware breakpoint at these three addresses.
5. When the program runs to the entrance of the main function, it needs to record the register information and dump part of the memory information. After recording, let the program continue to execute.
6. Return to the QEMU console, and then return to the process, directly enter the CTRL + Z key combination to suspend the process, and then check the process memory distribution after checking the process PID. The subsequent dump process memory needs the size and starting address of the segment.
7. After continuing to execute, we first switch QEMU from console mode to guest, and then enter the value to be read by the process scanf function. When we call the put function, it will break, and then we can dump more memory of the process.
8. Dump the memory of the process. In the process described in this paper, 0x00010000-0x00023000 are dumped, 0x00023000-0x00025000, 0x00025000-0x00026000, 0x3ffffc32000-0x3ffffc34000. The memory of dump will be saved in the directory of starting QEMU.
9. Then use unicorn and capstone framework to simulate the code under dump in the process. First, add the code to simulate the correct input and output, and then we try to modify the jump to enter the wrong data, but the input is successful.
四、 Simulation process
1. First, simulate the memory process running after the previous dump. There is scanf input in it. We can judge the address analog input. Finally, we can set a breakpoint at the two puts functions. After breaking, we can judge the correct characters one by one according to the number of running instructions. Finally, attach the code:
riscv64.h:
#pragma once
#pragma pack(push,1)
typedef union
{
DWORD64 all_reg[33];
struct
{
DWORD64 r_x0; // <<== 0
DWORD64 r_x1;
DWORD64 r_x2;
DWORD64 r_x3;
DWORD64 r_x4;
DWORD64 r_x5; // <<== 5
DWORD64 r_x6;
DWORD64 r_x7;
DWORD64 r_x8;
DWORD64 r_x9;
DWORD64 r_x10; // <<== 10
DWORD64 r_x11;
DWORD64 r_x12;
DWORD64 r_x13;
DWORD64 r_x14;
DWORD64 r_x15; // <<== 15
DWORD64 r_x16;
DWORD64 r_x17;
DWORD64 r_x18;
DWORD64 r_x19;
DWORD64 r_x20; // <<== 20
DWORD64 r_x21;
DWORD64 r_x22;
DWORD64 r_x23;
DWORD64 r_x24;
DWORD64 r_x25; // <<== 25
DWORD64 r_x26;
DWORD64 r_x27;
DWORD64 r_x28;
DWORD64 r_x29;
DWORD64 r_x30; // <<== 30
DWORD64 r_x31;
DWORD64 r_pc;
}reg_x;
struct
{
DWORD64 r_zero ; // <<== 0
DWORD64 r_ra ;
DWORD64 r_sp ;
DWORD64 r_gp ;
DWORD64 r_tp ;
DWORD64 r_t0 ; // <<== 5
DWORD64 r_t1 ;
DWORD64 r_t2 ;
DWORD64 r_s0_fp ;
DWORD64 r_s1 ;
DWORD64 r_a0 ; // <<== 10
DWORD64 r_a1 ;
DWORD64 r_a2 ;
DWORD64 r_a3 ;
DWORD64 r_a4 ;
DWORD64 r_a5 ; // <<== 15
DWORD64 r_a6 ;
DWORD64 r_a7 ;
DWORD64 r_s2 ;
DWORD64 r_s3 ;
DWORD64 r_s4 ; // <<== 20
DWORD64 r_s5 ;
DWORD64 r_s6 ;
DWORD64 r_s7 ;
DWORD64 r_s8 ;
DWORD64 r_s9 ; // <<== 25
DWORD64 r_s10 ;
DWORD64 r_s11 ;
DWORD64 r_t3 ;
DWORD64 r_t4 ;
DWORD64 r_t5 ; // <<== 30
DWORD64 r_t6 ;
DWORD64 r_pc ;
}reg;
}REG_RISCV64;
typedef struct _FileInformation_
{
_In_ PVOID BaseAddress;
_In_ ULONG FileSize;
_In_ LPCWSTR FileName;
_Out_ PVOID buffer;
}FileInformation, * pFileInformation;
#pragma pop
extern BYTE g_num[];
extern DWORD64 g_riscv64_instruction_count;
VOID riscv64_init_registers();
VOID riscv64_emulate();
VOID riscv64_read_uc_registers();
VOID riscv64_write_uc_registers();
VOID riscv64_print_uc_registers();
VOID riscv64_print_uc_stack(DWORD64 rsp);
riscv64.c
#include "common.h"
csh g_riscv64_cs_handle = NULL;
cs_insn* g_riscv64_cs_insn = NULL;
size_t g_riscv64_cs_count = 0; // how many instruction that this capstone API disassembly successfully
cs_err g_riscv64_cs_err = CS_ERR_OK;
uc_engine* g_riscv64_uc = NULL;
uc_err g_riscv64_uc_err = UC_ERR_OK; // error number that unicorn emulate instruction
DWORD64 g_riscv64_instruction_count = 0;
REG_RISCV64 g_riscv64_reg = { 0 }; // init register
BYTE ret = 1;
BYTE g_num[] = { '1','3','7', '5','5','8','9', '1','2','3','4' };
//#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00"
VOID riscv64_init_registers()
{
//g_riscv64_reg.reg.r_zero = 0x0;
g_riscv64_reg.reg.r_ra = 0x10104;
g_riscv64_reg.reg.r_sp = 0x3fff842df0;
g_riscv64_reg.reg.r_gp = 0x24420;
g_riscv64_reg.reg.r_tp = 0x1ba710;
g_riscv64_reg.reg.r_t0 = 0x100e0;
g_riscv64_reg.reg.r_t1 = 0xf;
g_riscv64_reg.reg.r_t2 = 0x3ff;
g_riscv64_reg.reg.r_s0_fp= 0x1bbcc0;
g_riscv64_reg.reg.r_s1 = 0x1bbc90;
g_riscv64_reg.reg.r_a0 = 0x1;
g_riscv64_reg.reg.r_a1 = 0x3fff842df8;
g_riscv64_reg.reg.r_a2 = 0x0;
g_riscv64_reg.reg.r_a3 = 0x10;
g_riscv64_reg.reg.r_a4 = 0x1;
g_riscv64_reg.reg.r_a5 = 0x0;
g_riscv64_reg.reg.r_a6 = 0x1f;
g_riscv64_reg.reg.r_a7 = 0xdd;
g_riscv64_reg.reg.r_s2 = 0x1bbcd0;
g_riscv64_reg.reg.r_s3 = 0x1a3ab2;
g_riscv64_reg.reg.r_s4 = 0x15c2e8;
g_riscv64_reg.reg.r_s5 = 0x1b8558;
g_riscv64_reg.reg.r_s6 = 0x8;
g_riscv64_reg.reg.r_s7 = 0x0;
g_riscv64_reg.reg.r_s8 = 0x0;
g_riscv64_reg.reg.r_s9 = 0x1bd8f0;
g_riscv64_reg.reg.r_s10 = 0x1bbcc0;
g_riscv64_reg.reg.r_s11 = 0x1;
g_riscv64_reg.reg.r_t3 = 0xffffffffffffffff;
g_riscv64_reg.reg.r_t4 = 0xf;
g_riscv64_reg.reg.r_t5 = 0x2;
g_riscv64_reg.reg.r_t6 = 0x1;
g_riscv64_reg.reg.r_pc = 0x101cc;
}
FileInformation fileinfo[] =
{
// BaseAddress FileSize Path allocate buffer address
(PVOID)0x00010000 , 0x13000 , L".\\riscv64_dump\\00010000-00023000.dump" , NULL , //.text
(PVOID)0x00023000 , 0x2000 , L".\\riscv64_dump\\00023000-00025000.dump" , NULL , //.stack
(PVOID)0x00025000 , 0x1000 , L".\\riscv64_dump\\00025000-00026000.dump" , NULL , //.rdata
(PVOID)0x3fff841000 , 0x2000 , L".\\riscv64_dump\\3fff841000-3fff843000.dump" , NULL , //.data
};
VOID riscv64_emulate()
{
g_riscv64_cs_err = cs_open(CS_ARCH_RISCV, CS_MODE_RISCVC, &g_riscv64_cs_handle);
g_riscv64_uc_err = uc_open(UC_ARCH_RISCV, UC_MODE_RISCV64, &g_riscv64_uc);
if (g_riscv64_cs_err || g_riscv64_uc_err)
{
printf("ERROR: Failed to initialize engine!\n");
return;
}
cs_option(g_riscv64_cs_handle, CS_OPT_DETAIL, CS_OPT_ON);
for (ULONG i = 0; i < sizeof(fileinfo) / sizeof(fileinfo[0]); i++)
{
FILE* pFile = NULL;
fileinfo[i].buffer = (PVOID)malloc(fileinfo[i].FileSize);
if (!fileinfo[i].buffer)
{
printf("Allocate mem fail!\n");
return;
}
pFile = _wfopen(fileinfo[i].FileName, L"rb");
if (!pFile)
{
printf("open file error code : <%d>\n", GetLastError());
return;
}
fread(fileinfo[i].buffer, fileinfo[i].FileSize, 1, pFile);
if (pFile)
fclose(pFile);
g_riscv64_uc_err = uc_mem_map(g_riscv64_uc, (DWORD64)fileinfo[i].BaseAddress, fileinfo[i].FileSize, UC_PROT_ALL);
if (g_riscv64_uc_err)
{
printf("uc mem map error!Error Code:<%d>\n", g_riscv64_uc_err);
return;
}
g_riscv64_uc_err = uc_mem_write(g_riscv64_uc, (DWORD64)fileinfo[i].BaseAddress, fileinfo[i].buffer, fileinfo[i].FileSize);
if (g_riscv64_uc_err)
{
printf("uc mem write error!Error Code:<%d>\n", g_riscv64_uc_err);
return;
}
}
riscv64_init_registers();
riscv64_write_uc_registers();
BYTE Code[32] = { 0 };
int abcde = 0;
do
{
uc_mem_read(g_riscv64_uc, g_riscv64_reg.reg.r_pc, Code, sizeof(Code));
g_riscv64_cs_count = cs_disasm(g_riscv64_cs_handle, Code, sizeof(Code), g_riscv64_reg.reg.r_pc, 1, &g_riscv64_cs_insn);
if (!g_riscv64_cs_count)
{
g_riscv64_cs_err = cs_open(CS_ARCH_RISCV, CS_MODE_RISCV64, &g_riscv64_cs_handle);
g_riscv64_cs_count = cs_disasm(g_riscv64_cs_handle, Code, sizeof(Code), g_riscv64_reg.reg.r_pc, 1, &g_riscv64_cs_insn);
if (!g_riscv64_cs_count)
break;
g_riscv64_cs_err = cs_open(CS_ARCH_RISCV, CS_MODE_RISCVC, &g_riscv64_cs_handle);
}
g_riscv64_uc_err = uc_emu_start(g_riscv64_uc, g_riscv64_reg.reg.r_pc, 0xffffffffffffffff, 0, 1);
riscv64_read_uc_registers();
//riscv64_print_uc_registers();
//riscv64_print_uc_stack(g_riscv64_reg.reg.r_sp);
if (g_riscv64_reg.reg.r_pc == 0x101e4)
{
char a[10][32] = { 0 };
ULONG64 temp = NULL;
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a0), &a[0][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a1), &a[1][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a2), &a[2][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a3), &a[3][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a4), &a[4][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a5), &a[5][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a6), &a[6][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a7), &a[7][0], sizeof(a[0]));
g_riscv64_reg.reg.r_pc += g_riscv64_cs_insn->size;
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_PC, &g_riscv64_reg.reg.r_pc);
uc_mem_write(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a0), &ret, sizeof(ret));
uc_mem_write(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a1), g_num, sizeof(g_num));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a0), &a[0][0], 32);
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a1), &a[1][0], 32);
int asd = 1;
}
else if (g_riscv64_reg.reg.r_pc == 0x10204
|| g_riscv64_reg.reg.r_pc == 0x10212
|| g_riscv64_cs_count == 0
)
{
char a[10][32] = { 0 };
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a0), &a[0][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a1), &a[1][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a2), &a[2][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a3), &a[3][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a4), &a[4][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a5), &a[5][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a6), &a[6][0], sizeof(a[0]));
uc_mem_read(g_riscv64_uc, (DWORD64)(g_riscv64_reg.reg.r_a7), &a[7][0], sizeof(a[0]));
return;
int abc = 3;
}
cs_free(g_riscv64_cs_insn, 1);
if (g_riscv64_uc_err)
{
printf("uc_emu_start error!Error Code:<%d>\n", g_riscv64_uc_err);
break;
}
g_riscv64_instruction_count++;
} while (g_riscv64_cs_count);
cs_close(&g_riscv64_cs_handle);
uc_close(g_riscv64_uc);
}
VOID riscv64_read_uc_registers()
{
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_ZERO , &g_riscv64_reg.reg.r_zero); //<==0
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_RA , &g_riscv64_reg.reg.r_ra);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_SP , &g_riscv64_reg.reg.r_sp);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_GP , &g_riscv64_reg.reg.r_gp);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_TP , &g_riscv64_reg.reg.r_tp);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_T0 , &g_riscv64_reg.reg.r_t0); //<==5
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_T1 , &g_riscv64_reg.reg.r_t1);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_T2 , &g_riscv64_reg.reg.r_t2);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_S0 , &g_riscv64_reg.reg.r_s0_fp);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_S1 , &g_riscv64_reg.reg.r_s1);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_A0 , &g_riscv64_reg.reg.r_a0); //<==10
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_A1 , &g_riscv64_reg.reg.r_a1);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_A2 , &g_riscv64_reg.reg.r_a2);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_A3 , &g_riscv64_reg.reg.r_a3);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_A4 , &g_riscv64_reg.reg.r_a4);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_A5 , &g_riscv64_reg.reg.r_a5); //<==15
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_A6 , &g_riscv64_reg.reg.r_a6);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_A7 , &g_riscv64_reg.reg.r_a7);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_S2 , &g_riscv64_reg.reg.r_s2);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_S3 , &g_riscv64_reg.reg.r_s3);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_S4 , &g_riscv64_reg.reg.r_s4); //<==20
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_S5 , &g_riscv64_reg.reg.r_s5);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_S6 , &g_riscv64_reg.reg.r_s6);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_S7 , &g_riscv64_reg.reg.r_s7);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_S8 , &g_riscv64_reg.reg.r_s8);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_S9 , &g_riscv64_reg.reg.r_s9); //<==25
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_S10 , &g_riscv64_reg.reg.r_s10);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_S11 , &g_riscv64_reg.reg.r_s11);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_T3 , &g_riscv64_reg.reg.r_t3);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_T4 , &g_riscv64_reg.reg.r_t4);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_T5 , &g_riscv64_reg.reg.r_t5); //<==30
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_T6 , &g_riscv64_reg.reg.r_t6);
uc_reg_read(g_riscv64_uc, UC_RISCV_REG_PC , &g_riscv64_reg.reg.r_pc);
}
VOID riscv64_write_uc_registers()
{
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_ZERO, &g_riscv64_reg.reg.r_zero); //<==0
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_RA, &g_riscv64_reg.reg.r_ra);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_SP, &g_riscv64_reg.reg.r_sp);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_GP, &g_riscv64_reg.reg.r_gp);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_TP, &g_riscv64_reg.reg.r_tp);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_T0, &g_riscv64_reg.reg.r_t0); //<==5
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_T1, &g_riscv64_reg.reg.r_t1);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_T2, &g_riscv64_reg.reg.r_t2);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_S0, &g_riscv64_reg.reg.r_s0_fp);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_S1, &g_riscv64_reg.reg.r_s1);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_A0, &g_riscv64_reg.reg.r_a0); //<==10
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_A1, &g_riscv64_reg.reg.r_a1);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_A2, &g_riscv64_reg.reg.r_a2);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_A3, &g_riscv64_reg.reg.r_a3);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_A4, &g_riscv64_reg.reg.r_a4);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_A5, &g_riscv64_reg.reg.r_a5); //<==15
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_A6, &g_riscv64_reg.reg.r_a6);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_A7, &g_riscv64_reg.reg.r_a7);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_S2, &g_riscv64_reg.reg.r_s2);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_S3, &g_riscv64_reg.reg.r_s3);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_S4, &g_riscv64_reg.reg.r_s4); //<==20
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_S5, &g_riscv64_reg.reg.r_s5);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_S6, &g_riscv64_reg.reg.r_s6);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_S7, &g_riscv64_reg.reg.r_s7);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_S8, &g_riscv64_reg.reg.r_s8);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_S9, &g_riscv64_reg.reg.r_s9); //<==25
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_S10, &g_riscv64_reg.reg.r_s10);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_S11, &g_riscv64_reg.reg.r_s11);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_T3, &g_riscv64_reg.reg.r_t3);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_T4, &g_riscv64_reg.reg.r_t4);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_T5, &g_riscv64_reg.reg.r_t5); //<==30
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_T6, &g_riscv64_reg.reg.r_t6);
uc_reg_write(g_riscv64_uc, UC_RISCV_REG_PC, &g_riscv64_reg.reg.r_pc);
}
VOID riscv64_print_uc_registers()
{
printf("\n>--- --- --- %lld --- --- ---<\n", g_riscv64_instruction_count);
printf("%#16llx:\t%s\t%s\n", g_riscv64_cs_insn[0].address, g_riscv64_cs_insn[0].mnemonic, g_riscv64_cs_insn[0].op_str);
printf("zero =0x%16llx\n", g_riscv64_reg.reg.r_zero);
printf("ra =0x%16llx\n", g_riscv64_reg.reg.r_ra);
printf("sp =0x%16llx\n", g_riscv64_reg.reg.r_sp);
printf("gp =0x%16llx\n", g_riscv64_reg.reg.r_gp);
printf("tp =0x%16llx\n", g_riscv64_reg.reg.r_tp);
printf("t0 =0x%16llx\n", g_riscv64_reg.reg.r_t0);
printf("t1 =0x%16llx\n", g_riscv64_reg.reg.r_t1);
printf("t2 =0x%16llx\n", g_riscv64_reg.reg.r_t2);
printf("s0/fp=0x%16llx\n", g_riscv64_reg.reg.r_s0_fp);
printf("s1 =0x%16llx\n", g_riscv64_reg.reg.r_s1);
printf("a0 =0x%16llx\n", g_riscv64_reg.reg.r_a0);
printf("a1 =0x%16llx\n", g_riscv64_reg.reg.r_a1);
printf("a2 =0x%16llx\n", g_riscv64_reg.reg.r_a2);
printf("a3 =0x%16llx\n", g_riscv64_reg.reg.r_a3);
printf("a4 =0x%16llx\n", g_riscv64_reg.reg.r_a4);
printf("a5 =0x%16llx\n", g_riscv64_reg.reg.r_a5);
printf("a6 =0x%16llx\n", g_riscv64_reg.reg.r_a6);
printf("a7 =0x%16llx\n", g_riscv64_reg.reg.r_a7);
printf("s2 =0x%16llx\n", g_riscv64_reg.reg.r_s2);
printf("s3 =0x%16llx\n", g_riscv64_reg.reg.r_s3);
printf("s4 =0x%16llx\n", g_riscv64_reg.reg.r_s4);
printf("s5 =0x%16llx\n", g_riscv64_reg.reg.r_s5);
printf("s6 =0x%16llx\n", g_riscv64_reg.reg.r_s6);
printf("s7 =0x%16llx\n", g_riscv64_reg.reg.r_s7);
printf("s8 =0x%16llx\n", g_riscv64_reg.reg.r_s8);
printf("s9 =0x%16llx\n", g_riscv64_reg.reg.r_s9);
printf("s10 =0x%16llx\n", g_riscv64_reg.reg.r_s10);
printf("s11 =0x%16llx\n", g_riscv64_reg.reg.r_s11);
printf("t3 =0x%16llx\n", g_riscv64_reg.reg.r_t3);
printf("t4 =0x%16llx\n", g_riscv64_reg.reg.r_t4);
printf("t5 =0x%16llx\n", g_riscv64_reg.reg.r_t5);
printf("t6 =0x%16llx\n", g_riscv64_reg.reg.r_t6);
printf("pc =0x%16llx\n", g_riscv64_reg.reg.r_pc);
}
VOID riscv64_print_uc_stack(DWORD64 rsp)
{
DWORD64 val = 0;
for (ULONG i = 5; i > 0; i--)
{
uc_mem_read(g_riscv64_uc, (DWORD64)(rsp - i * 8), &val, sizeof(DWORD64));
printf("\t|%16llx|\n", val);
}
uc_mem_read(g_riscv64_uc, (DWORD64)rsp, &val, sizeof(DWORD64));
printf("===> |%16llx|\n", val);
for (ULONG i = 1; i < 5; i++)
{
uc_mem_read(g_riscv64_uc, (DWORD64)(rsp + i * 8), &val, sizeof(DWORD64));
printf("\t|%16llx|\n", val);
}
}
This is the result diagram of the test output:
Obviously, the first character is 1, which is different from the number of instructions executed by other numbers.
2. Modify the jump judgment of whether the return value of the judgment string is True. According to subsection RVC Instruction Set Listings in “C” Standard Extension for Compressed Instructions, Version 2.0 in The RISC-V Instruction Set Manual:
We can modify the value of the A5 register at the 101fa: cb81 beqz a5,1020a <main+0x3e>instruction, and can modify the instruction to unconditional jump, which can successfully output right!
The steps are very simple. Just judge the address and then modify the value in the register. I won't repeat it here.
Reference for this article:The RISC-V Instruction Set Manual Volume I: Unprivileged ISA Document Version 20191213
There are still many shortcomings in the learning process, and I hope my friends will correct me if anything unclear or incorrect. Thank you!
边栏推荐
- 在全志V853开发板试编译QT测试
- 【周赛复盘】LeetCode第304场单周赛
- #yyds dry goods inventory# Interview must brush TOP101: the last k nodes in the linked list
- Map by value
- 首篇 NLP 领域图神经网络综述:127 页,从图构建到实际应用面面观
- 即时通讯开发移动端弱网络优化方法总结
- 2022,程序员应该如何找工作
- PanGu-Coder:函数级的代码生成模型
- How to query database configuration parameters in GBase 8c, such as datestyle.What function or syntax to use?
- explain each field introduction
猜你喜欢
Summer vacation second week wrap-up blog
Zabbix6.0钉钉机器人告警
C#/VB.NET:从 PDF 文档中提取所有表格
odoo 编码规范(编程规范、编码指南)
明日盛会|ApacheCon Asia 2022 Pulsar 技术议题一览
【蓝桥杯选拔赛真题47】Scratch潜艇游戏 少儿编程scratch蓝桥杯选拔赛真题讲解
通配符 SSL/TLS 证书
Screen: GFF, OGS, Oncell, Incell of full lamination process
Win11如何开启剪贴板自动复制?Win11开启剪贴板自动复制的方法
#yyds dry goods inventory# Interview must brush TOP101: the last k nodes in the linked list
随机推荐
用VS2013编译带boost库程序时提示 fatal error C1001: 编译器中发生内部错误
Screenshot of Selenium in Remote
Go GORM transaction instance analysis
Tencent Cloud Hosting Security x Lightweight Application Server | Powerful Joint Hosting Security Pratt & Whitney Version Released
如何看待腾讯云数据库负责人林晓斌借了一个亿炒股?
力扣刷题之移动零
力扣刷题之合并两个有序数组
Screen: GFF, OGS, Oncell, Incell of full lamination process
首篇 NLP 领域图神经网络综述:127 页,从图构建到实际应用面面观
有点奇怪!访问目的网址,主机能容器却不行
shell脚本专题(07):文件由cfs到bos
【蓝桥杯选拔赛真题47】Scratch潜艇游戏 少儿编程scratch蓝桥杯选拔赛真题讲解
在全志V853开发板试编译QT测试
LeetCode 1374. Generate an odd number of each character string
短视频软件开发,Android开发,使用Kotlin实现WebView
What are the application advantages of SaaS management system?How to efficiently improve the digital and intelligent development level of food manufacturing industry?
Multi-Party Threshold Private Set Intersection with Sublinear Communication-2021: Interpretation
Choosing the right DevOps tool starts with understanding DevOps
屏:全贴合工艺之GFF、OGS、Oncell、Incell
What should I do if the Win11 campus network cannot be connected?Win11 can't connect to campus network solution