GDB 有一个x/i命令(还有disassemble),它允许查看给定地址的指令。
我们如何做相反的事情——组装一条指令并写入给定的地址?
GDB 有一个x/i命令(还有disassemble),它允许查看给定地址的指令。
我们如何做相反的事情——组装一条指令并写入给定的地址?
GDB 似乎没有任何本机命令来组装指令。但是我们可以使用它的 Python 脚本工具来创建一个自定义命令,该命令将准备一个汇编源文件,将其提供给汇编器,并将结果字节写入下级地址空间。
这是一个.gdbinit用于 x86/x86_64 的Python 脚本示例(您可以将其粘贴到您的),使用 FASM 作为汇编程序:
python
from tempfile import mkstemp
import subprocess
import os
class Assemble(gdb.Command):
"""Assemble an instruction
Usage: assemble 0xADDRESS instruction to assemble
"""
def __init__(self):
super(Assemble, self).__init__("assemble", gdb.COMMAND_DATA, gdb.COMPLETE_NONE, True)
def invoke(self, arg, from_tty):
argPieces=arg.split()
try:
# addresses like those resulting from $pc can have trailing
# junk, which we'll clear here by conversion to long
address=gdb.execute('printf "%#lx",'+argPieces[0], to_string=True)
except:
print("Failed to parse address")
return
instruction=" ".join(argPieces[1:])
bits=format(8*int(gdb.parse_and_eval("sizeof(void*)")),"d")
fd,srcPath=mkstemp(prefix="gdb_asm_")
src=os.fdopen(fd, 'w')
src.write("use%s\norg %s\n%s\n" % (bits, address, instruction))
src.close()
try:
subprocess.check_output(["fasm",srcPath], stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as err:
print("Assembler failed with exit code", err.returncode)
print("Output:", err.output)
os.remove(srcPath)
return
os.remove(srcPath)
binPath=srcPath+".bin"
binaryFile=open(binPath, 'rb')
offset=0
while True:
byteStr=binaryFile.read(1)
if not byteStr:
break
byte=byteStr[0]
if not isinstance(byte, int): # compatibility with python 2
byte=ord(byte)
gdb.execute("set *(unsigned char*)("+address+'+'+
format(offset,'d')+")="+format(byte,"#02x"))
offset+=1
binaryFile.close()
os.remove(binPath)
if offset==0:
print("Assembler output an empty file")
return
gdb.execute("x/i "+address)
Assemble()
end
然后你会像这样使用它
gdb -q -ex starti /bin/true
Reading symbols from /bin/true...(no debugging symbols found)...done.
Starting program: /bin/true
Program stopped.
0xf7fdd800 in _start () from /lib/ld-linux.so.2
(gdb) disas
Dump of assembler code for function _start:
=> 0xf7fdd800 <+0>: mov eax,esp
0xf7fdd802 <+2>: call 0xf7fe2160 <_dl_start>
(gdb) assemble $pc+2 mov ebp, [esi+235+edx*2]
0xf7fdd802 <_start+2>: mov ebp,DWORD PTR [esi+edx*2+0xeb]
compile code 命令
7.9左右引入,允许在当前位置进行代码编译和注入,文档:https : //sourceware.org/gdb/onlinedocs/gdb/Compiling-and-Injecting-Code.html
我在以下位置给出了一个最小的可运行示例:https : //stackoverflow.com/questions/5480868/how-to-call-assembly-in-gdb/31709579#31709579
我不知道如何在特定位置注入,但是如果您对此很认真,在扩展compile code功能中修补此功能可能是要走的路。
这是可能的,但非常复杂!!不管gdb,你都可以做到以下几点: