欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]x64dbg脚本 - 解决调试时编排函数调用

[原创]x64dbg脚本 - 解决调试时编排函数调用

x64dbg脚本 - 解决调试时自定义调用函数方式

一直没怎么使用x64dbg脚本功能,而且官方的文档命令的例子也不多,所以整理了下,解决的问题来原于这次Q3的CTF第5题,在做3DES的时候,程序逻辑为:

           Dest= UserInput[18, 8] 

           v21 = UserInput[16, 8]; = "VXV9/DCo" 

           v22 = UserInput[8, 8];  = "VXV8/wCp" 

           v23 = UserInput[0, 8];  = "VXX/8AKl" 

           des_Func_en(&Dest, &v21, &Dest); // crypt

           des_Func_de(&Dest, &v22, &Dest); // decrypt

           des_Func_en(&Dest, &v23, &Dest); // crypt

           // 执行后此处Dest =  ['0x30', '0x80', '0x3', '0x3f', '0xfd', '0x55', '0x5a', '0x80']

上面的CTF相关的内容就略了,其中需要逆向得到Dest的值,需要对上面的三次调用逆过程执行,基本为:

           Dest =  ['0x30', '0x80', '0x3', '0x3f', '0xfd', '0x55', '0x5a', '0x80']

           v21 = UserInput[16, 8]; = "VXV9/DCo" 

           v22 = UserInput[8, 8];  = "VXV8/wCp" 

           v23 = UserInput[0, 8];  = "VXX/8AKl" 

           des_Func_de(&Dest, &v23, &Dest); // decrypt

           des_Func_en(&Dest, &v22, &Dest); // crypt

           des_Func_de(&Dest, &v21, &Dest); // decrypt

如果手工调试,可以在断点到对应函数后,通过修改参数来实现,但是因为顺序问题,需要3次完成调试,其中在使用脚本语言相关的调试的时候,是可以在调试阶段,动态去调用一些函数,来测试结果的,所以想着是不是有办法做到类似的功能(本来想看是不是有插件可以,没有找到),就开始找办法实现。

实现思路

在二进制里要实现上面的调用,想到的一个思路是通过动态写汇编来执行:
1,先创建一块调试临时内存区域用来存放需要写的汇编;
2,将上面的逆过程以汇编的方式写到内存区域;
3,在调试的时候,执行到合适的断点后,进入上面的汇编获取结果;
根据上面的方式,分别要解决几个问题:
1,内存分配:alloc
2,des_Func_de|des_Func_en的调用参数和地址:通过查看原来的内容获取:

// des_Func_en :

lea rcx,qword ptr ss:[rbp-10]         

lea rdx,qword ptr ss:[rbp-40]         

lea rax,qword ptr ss:[rbp-10]         

mov r8,rcx                            

mov rcx,rax                           

call <lost.sub_4023E4_DES_Func_en>              | call 4023E4(rcx, rdx, r8)

// des_Func_den :

lea rcx,qword ptr ss:[rbp-10]                   

lea rdx,qword ptr ss:[rbp-30]                   

lea rax,qword ptr ss:[rbp-10]                   

mov r8,rcx                                      

mov rcx,rax                                     

call <lost.sub_40202A_DES_Func_de>              | call 40202A(rcx, rdx, r8)

des_Func_de :
3, 写入汇编还是shellcode ?通过查看手册,其实x64dbg的汇编器是可以调用的:asm 命令;
接下来就是coding和debug的过程,不细说了,有一些命令不熟悉,自己也摸索了下;

脚本结果:

// This is a demo of x64dbg 

// In x64dbg script, use cmp and je to work like "if and for " in high class language.

// Note: 22fd30, 22fd20, 22fd10, 22fd00 are fixed addresses in debug. 

// ------------------------------------------------------------------------------------

// set dest = ['0x30', '0x80', '0x3', '0x3f', '0xfd', '0x55', '0x5a', '0x80'] 

Fill 22FD30,30,1;Fill 22FD30+1,80,1;Fill 22FD30+2,03,1;

Fill 22FD30+3,3F,1;Fill 22FD30+4,FD,1;Fill 22FD30+5,55,1;

Fill 22FD30+6,5A,1;Fill 22FD30+7,80,1;

// allocate memory , note: set @address may get faliure.

alloc 0x1000

// write code to memory 

$inst_base=$result + 0x10

$inst_offset=0

asm $inst_base, "mov edx, 0x22FD20"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "lea rcx, ss:[rbp-0x10]"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "lea rax, ss:[rbp-0x10]"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "mov r8, rcx"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "mov rcx, rax"

$inst_offset = $inst_offset + $result

log "inst_offset = {0}, result = {1}", $inst_offset, $result

// call 0x40202A(rcx, rdx, r8)

asm $inst_base + $inst_offset, "call 0x40202A"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "lea rcx, ss:[rbp-0x10]"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "lea rax, ss:[rbp-0x10]"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "mov r8, rcx"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "mov rcx, rax"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "mov edx, 0x22FD10"

$inst_offset = $inst_offset + $result

// call 0x4023E4(rcx, rdx, r8)

asm $inst_base + $inst_offset, "call 0x4023E4"

log "inst_offset = {0}, result = {1}", $inst_offset, $result

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "lea rcx, ss:[rbp-0x10]"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "lea rax, ss:[rbp-0x10]"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "mov r8, rcx"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "mov rcx, rax"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "mov edx, 0x22FD00"

$inst_offset = $inst_offset + $result

// call 0x40202A(rcx, rdx, r8)

asm $inst_base + $inst_offset, "call 0x40202A"

$inst_offset = $inst_offset + $result

asm $inst_base + $inst_offset, "nop"

bp $inst_base + $inst_offset

log "inst_offset = {0}, result = {1}", $inst_offset, $result

// set run point 

rip = $inst_base

run

log "Result = 0x" "{x:bswap([0x22FD30])}" // show 8 bytes info of address 22fd30.

log "Result = 0x" "{mem;8@0x22FD30}"      // Demo how to set size of showed bytes.

说明:最后Demo了一下按字节显示的格式,官方文档没提命令需要加“”,而且有一些格式不加“”也可以,有点乱。

测试结果

完成上面的脚本后,加载lost.exe程序,手动设置断点:

程序正常输入:VXX/8AKlVXV8/wCpVXV9/DCo
停在断点后,加载脚本,并执行,在日志界面查看结果:

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功