记录学习到的patch方法.主要针对CTFpwn. 供自己以后忘记的时候查阅…

start

主要来源p4nda

IDA

IDApatch主要是原有的patch功能和添加的插件例如keypatch

keypatch

安装(for mac): https://github.com/fjh658/keystone-engine https://github.com/keystone-engine/keypatch

git clone https://github.com/fjh658/keystone-engine.git
cd keystone-engine
git submodule update --init --recursive
sudo python setup.py install --verbose
cp -rf  /usr/local/lib/python2.7/site-packages/keystone /Applications/IDA\ Pro\ 7.0/ida.app/Contents/MacOS/python/
brew install cmake 

使用

  • control+option+k可以直接打汇编指令也可以用符号.(长度不足补齐nop)
  • 右键可以search 汇编指令

    替换某个函数

    这个还不知道keypatch咋整…如果使用patchpyte过程如下 例如替换printfputscall printf ======>call puts

  • 原来的值 old
  • puts@plt
  • printf@plt
  • new_address:(old+puts-printf)

    缺点

    改变比较有限,不能call 没有plt的函数.不能hook

lief

mac上没装成功ubuntu好像直接pip install lief就可以了 说明文档太长还没去看… https://lief.quarkslab.com/doc/latest/api/python/elf.html#segment

rude_patch

直接改strtab 例如fmtstr漏洞修复:printf==>puts (注意这里比较暴力注意其他地方有没有用printf的,是否受影响…) 脚本如下

# @n132
import lief
import os
name="./main"
binary=lief.parse(name)
for x in binary.imported_symbols:
	if x.name=="printf":
		x.name="puts"
		print "[+]:printf fixed"
binary.write("patched_file")
os.system("chmod +x patched_file")

ADD Seg

主要是增加一个段可以增加编译的hook函数 例如

void diy(char *a){
	asm(
		"mov %rdi,0x68732f6e69622f\n"
		"push %rdi\n"
		"mov %rdi,%rsp\n"
		"xor %rsi,%rsi\n"
		"xor %rdx,%rdx\n"
		"mov %ral,0x3b\n"
		"syscall\n"
		);
}

//gcc -Os -nostdlib -nodefaultlibs -fPIC -Wl,-shared hook.c -o hook

编译之后增加到binary里

import lief
binary=lief.parse("./main")
lib=lief.parse("./hook")	
segment_add = binary.add(lib.segments[0])
binary.write("new")

之后确定位置后hook

import lief
from pwn import *
def patch_call(file,where,aim,arch = "amd64"):
	aim = p32((end - (where + 5 )) & 0xffffffff)
	order = '\xe8'+aim#call aim
	file.patch_address(where,[ord(i) for i in order])
	binary.write("new")
raw_address=
aim_address=
patch_call(binary,raw_address,aim_address)

ADD to .eh_frame

为了防止增加了seg导致binary变化太大.可以直接把较小的hook函数写进.eh_frame 感觉一般来说0x100字节左右的空间很够用了…感觉很好的方法…

import lief
from  pwn import *
def patch_call(file,where,aim,arch = "amd64"):
	aim = p32((aim - (where + 5 )) & 0xffffffff)
	order = '\xe8'+aim#call aim
	file.patch_address(where,[ord(i) for i in order])
	binary.write("new")
binary=lief.parse("../main")
context.arch='amd64'
hook='''
xor rax,rax
xor rsi,rsi
xor rdx,rdx
mov rdi,0x68732f6e69622f
push rdi
mov rdi,rsp
mov al,0x3b
syscall
'''
hook=asm(hook)
en_frame=0x000000000000A18
binary.patch_address(en_frame,[ord(i) for i in hook])
raw_address=0x00000000000092F
aim_address=en_frame
patch_call(binary,raw_address,aim_address)
binary.write("new")