patchkit 挖个坑, 回头填上
LIEF 修改ELF 修改目标文件的导入符号:
示例程序:
#include <stdio.h> #include <stdlib.h> int main (int argc, char ** argv) { puts ("/bin/bash" ); return EXIT_SUCCESS; }
那么现在要把puts改成system:
import lieffile = lief.parse("test" ) puts_sym = filter(lambda e: e.name == "puts" , file.imported_symbols)[0 ] puts_sym.name = "system" file.write("test.patch" ) print("done" )
➜ LIEF_test ./test.patch
a@ubuntu:~/LIEF_test$ id
uid=1000(a) gid=1000(a) groups=1000(a),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
这种方法碰到uaf或者double free之类的很有用, 直接将malloc改为realloc, 这样创建chunk的时候会清空内存, 可以解决很多问题
示例题目:
修改libc 修改libc里的符号, 然后用LD_LIBRARY_PATH加载
import lieflibc = lief.parse('/lib/x86_64-linux-gnu/libc-2.23.so' ) puts_sym = filter(lambda e: e.name == "puts" , libc.dynamic_symbols)[0 ] system_sym = filter(lambda e: e.name == "system" , libc.dynamic_symbols)[0 ] puts_sym.name = "system" system_sym.name = "puts" libc.write("libc.so.6" )
然后export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH
即可
但是只能在当前shell中生效, 如果要在所有shell生效, 需要把下述语句写入~/.bash_profile
LD_LIBRARY_PATH=path:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
如果我们有bash_profile的读写权限的话, 完全可以删掉libc里的system和execve函数, 导致无法用libc getshell
修改库函数 碰到一些无法通过简单修改函数符号表之类的elf, 比如未检查size导致的堆溢出之类的, 我们需要增加一些代码来进行修改
测试程序:
#include <stdio.h> #include <stdlib.h> #include <math.h> int main (int argc, char **argv) { if (argc != 2 ) { printf ("Usage: %s <a> \n" , argv[0 ]); exit (-1 ); } int a = atoi(argv[1 ]); printf ("exp(%d) = %f\n" , a, exp (a)); return 0 ; }
我们的目标是把exp
函数改为我们自定义的hook
函数
double hook (double x) { return x + 100 ; }
编译: gcc -Os -nostdlib -nodefaultlibs -fPIC -Wl,-shared hook.c -o hook
jio本:
import lieflibm = lief.parse("/lib/x86_64-linux-gnu/libm-2.23.so" ) hook = lief.parse("hook" ) segment_added = libm.add(hook.segments[0 ]) print("Hook inserted at VA: 0x{:06x}" .format(segment_added.virtual_address)) exp_symbol = libm.get_symbol("exp" ) hook_symbol = hook.get_symbol("hook" ) exp_symbol.value = segment_added.virtual_address + hook_symbol.value libm.write("libm.so.6" )
这样就把libc里的exp函数改为我们的hook函数了
修改plt/got表 测试程序:
#include <stdio.h> #include <stdlib.h> #include <string.h> char password[] = "\x18\x3d\x31\x32\x03\x05\x33\x09\x03\x1b\x33\x28\x03\x08\x34\x39\x03\x1a\x30\x3d\x3b" ;inline int check (char * input) ;int check (char * input) { for (int i = 0 ; i < sizeof (password) - 1 ; ++i) { password[i] ^= 0x5c ; } return memcmp (password, input, sizeof (password) - 1 ); } int main (int argc, char **argv) { if (check(argv[1 ]) == 0 ) { puts ("You got it !!" ); return EXIT_SUCCESS; } puts ("Wrong" ); return EXIT_FAILURE; }
这里把memcpy修改为我们自己的memcpy, 把内容打印出来:
#include "arch/x86_64/syscall.c" #define stdout 1 int my_memcmp (const void * lhs, const void * rhs, int n) { const char msg[] = "Hook add\n" ; _write(stdout , msg, sizeof (msg)); _write(stdout , (const char *)lhs, n); _write(stdout , "\n" , 2 ); _write(stdout , (const char *)rhs, n); _write(stdout , "\n" , 2 ); return 0 ; }
jio本:
import liefcrackme = lief.parse("crackme.bin" ) hook = lief.parse("hook" ) segment_added = crackme.add(hook.segments[0 ]) my_memcmp = hook.get_symbol("my_memcmp" ) my_memcmp_addr = segment_added.virtual_address + my_memcmp.value crackme.patch_pltgot('memcmp' , my_memcmp_addr) crackme.write("crackme.hooked" )
参考 https://bbs.pediy.com/thread-222623.htm