当前位置:网站首页>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!
边栏推荐
- vtk体绘制代码报错的解决办法(代码在vtk7,8,9中都能运行),以及VTK数据集网站
- 面试必问的HashCode技术内幕
- SQL function TO_DATE (1)
- The elder brother of the goldfish RHCA memoirs: CL210 experiment management it network - chapter
- Use of message template placeholders
- kubernetes-部署nfs存储类
- 请你说说多线程
- modbus bus module DAM-8082
- Go GORM transaction instance analysis
- 力扣刷题之合并两个有序数组
猜你喜欢
通配符 SSL/TLS 证书
Screen: GFF, OGS, Oncell, Incell of full lamination process
【神经网络】一文带你轻松解析神经网络(附实例恶搞女友)
explain each field introduction
odoo 编码规范(编程规范、编码指南)
What should I do if the Win11 campus network cannot be connected?Win11 can't connect to campus network solution
即时通讯开发移动端弱网络优化方法总结
Summer vacation second week wrap-up blog
在Map传值与对象传值中模糊查询
力扣刷题之合并两个有序数组
随机推荐
明日盛会|ApacheCon Asia 2022 Pulsar 技术议题一览
odoo coding conventions (programming conventions, coding guidelines)
Library website construction source code sharing
英国伦敦大学|眼科强化学习:潜在应用和实施挑战
暑假第一周总结博客
Go GORM transaction instance analysis
Map by value
app直播源码,点击搜索栏自动弹出下拉框
30分钟成为Contributor|如何多方位参与OpenHarmony开源贡献?
金鱼哥RHCA回忆录:CL210管理OPENSTACK网络--网络配置选项
#yyds干货盘点# 面试必刷TOP101: 链表中倒数最后k个结点
【pyqt5】自定义控件 实现能够保持长宽比地缩放子控件
Win11如何删除升级包?Win11删除升级包的方法
Break the performance ceiling!AsiaInfo database supports more than 1 billion users, with a peak of one million transactions per second
短视频软件开发,Android开发,使用Kotlin实现WebView
屏:全贴合工艺之GFF、OGS、Oncell、Incell
#yyds dry goods inventory# Interview must brush TOP101: the last k nodes in the linked list
[pyqt5] Custom controls to achieve scaling sub-controls that maintain the aspect ratio
Selenium在远程中的截图
暑假第二周总结博客