# Debug & Load different version library ## 下載 source code 以及路徑設定 1. 可以參考[此 repo](https://github.com/matrix1001/glibc-all-in-one),來下載不同版本的 libc,我自己是直接從[這邊](https://mirror.tuna.tsinghua.edu.cn/ubuntu/pool/main/g/glibc/) or [這](https://ftp.gnu.org/gnu/glibc/)找 2. 將 debug symbol 的 libc 丟到 /usr/lib/debug (可能會很亂) 而這樣可以直接下載當前 libc 版本的 source code ``` sudo apt-get install glibc-source cd /usr/src/glibc sudo tar xvf glibc-2.31.tar.xz ``` ## gdb 設定 ### 載入不同版本的 libc ``` shell # 設定 LD_PRELOAD $gdb> set environment LD_PRELOAD=./libc.so $gdb> set exec-wrapper env "LD_PRELOAD=./libc-2.29.so" ``` ### 使用帶有 symbol 的 libc ``` shell # 設定 debug path $gdb> set debug-file-directory /usr/lib/debug/lib/x86_64-linux-gnu # 設定原始碼的路徑 $gdb> dir /usr/src/glibc/glibc-2.31/exit.c ``` [ref](https://stackoverflow.com/questions/10000335/how-to-use-debug-version-of-libc) ### 使用帶有 debug symbol 的 libc 下載 glibc 原始碼後 (/usr/src/glibc): ``` mkdir OWO && cd OWO ../glibc-2.31/configure --prefix $PWD --enable-debug --disable-werror make -j4 ``` - `elf/ld.so` 為 linker - `./libc.so` 為 libc 之後使用 ld_changer 改 binary 的 ld,用 `LD_PRELOAD=./libc.so ./binary` 來執行 ``` shell python3 ld_change.py ld.so test LD_PRELOAD=./libc.so ./test ``` ### 其他方法 ``` shell # 安裝帶有 debug symbols 的 libc sudo apt-get install libc6-dbg sudo cp /etc/apt/sources.list /etc/apt/sources.list~ # 將 source 的 repo 加到 apt 內 sudo sed -Ei 's/^# deb-src /deb-src /' /etc/apt/sources.list sudo apt-get update sudo apt install glibc-source ; 會在 /usr/src/glibc/ 拿到一包 glibc src code sudo tar xvf glibc-2.31.tar.xz ; 解壓縮 ``` ## command cheatsheet ### shell cheatsheet ``` - 看 got offset: objdump -R - 看保護機制: checksec - 靜態分析 asm: objdump -d - 看 lib info: ldd ./binary - 看 symbol offset: readelf -s - strace syscall: strace -e trace=read,write ./<elf> - checksec: 查看保護機制 - 查看 binary 的 pid: pidof <elf> - 看使用到的 linker and libc: ldd <elf> - LD_SHOW_AUXV=1 ./<elf> - ncat -vc <elf> -kl <127.0.0.1> <port>: 開啟 binary server (要裝 nmap) - ltrace: ltrace shows parameters of invoked functions and system calls ``` ### gdb cheatsheet ``` - reg info: info registers rax - info locals: 看 local var - print environ: 印出環境變數的 address - telescope 0x1234567(addr) 123(number): 印出 memory 的 content - set reg value: set $eip=0xValue - stack frame: stack 40 - gdb -q: quite 打開 gdb - b main: 在 main 設斷點 - r: run - vmmap: virtual memory map - x/40gx <address>: (g: 8 bytes, w: 4 bytes, b: 1 byte, s: string 到 `\x00`) - x/10i <address>: address 的 inst - set {long}0x123456789abc=1234: 修改某 memory address 的值 - i r: 查看 reg 的 value - xinfo <address>: 查看 address 的位址以及該區段的 info - s: 執行一行(若 function 則進入) - si: 執行一行 asm - fin: 執行 function 並跳回上層 - attach pid: debug running process - p var: print var 的 value - info function <function_name>: 查看 function - info locals: 看 local variable - info auxv: 看 auxiliary vector - lay asm - lay src - bt: back strace, 看 function stack - heapinfo 看 bin & chunk - heapbase heap base address - telescope - context: 重現當前 reg stack 的資料 ``` ld_change.py ``` python """ copy from jwang-a/CTF/master/utils/Pwn/LD_CHANGER.py """ ''' Copied and modified from https://www.cnblogs.com/0x636a/p/9157993.html All credits ro original author ''' from pwn import * import sys, os def change_ld(binary, ld): """ Force to use assigned new ld.so by changing the binary """ if not os.access(ld, os.R_OK): log.failure("Invalid path {} to ld".format(ld)) return None if not isinstance(binary, ELF): if not os.access(binary, os.R_OK): log.failure("Invalid path {} to binary".format(binary)) return None binary = ELF(binary) for segment in binary.segments: if segment.header['p_type'] == 'PT_INTERP': size = segment.header['p_memsz'] addr = segment.header['p_paddr'] data = segment.data() if size <= len(ld): log.failure("Failed to change PT_INTERP from {} to {}".format(data, ld)) return None binary.write(addr, ld.encode().ljust(size, b'\0')) path = binary.path.split('/')[-1][0].upper() if os.access(path, os.F_OK): os.remove(path) print("Removing exist file {}".format(path)) binary.save(path) os.chmod(path, 0b111000000) #rwx------ print("PT_INTERP has changed from {} to {}. Using temp file {}".format(data, ld, path)) return if len(sys.argv)!=3: print('Usage : python3 LD_PRELOAD.py [ld] [bin]') LD_PATH = sys.argv[1] ```