# 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]
```