一、編譯安裝
我在這里下載了libc的源代碼:wget http://ftp.gnu.org/gnu/glibc/glibc-2.31.tar.gz
(可以下載不同的版本,比如,把glibc-2.31換為glibc-2.27即可)
然后我們解壓它,拿到源代碼: tar -zxvf glibc-2.31.tar.gz
創建目錄等:
cd glibc-2.31
mkdir build && cd build
接着就是編譯安裝:
CFLAGS="-g -g3 -ggdb -gdwarf-4 -Og -Wno-error" \
CXXFLAGS="-g -g3 -ggdb -gdwarf-4 -Og -Wno-error"
sudo ../configure --prefix=/home/zq/Desktop/glibc-2.31/64 --disable-werror
sudo make
sudo make install
二、報錯和解決方案
在編譯的過程中遇到了如下問題:
(1)使用ubuntu 16 ,編譯libc-2.23和libc-2.27沒有問題,但是在libc-2.31的時候報錯:
*** These critical programs are missing or too old: compiler
應該是gcc的版本太低,升級的命令是這樣的:
sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt-get update sudo apt-get install gcc-9 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 100 sudo update-alternatives --config gcc
(2)*** These critical programs are missing or too old: gawk
解決辦法是:sudo apt-get install gawk
(3)
/tmp/ccD0p2ka.s: Assembler messages:
/tmp/ccD0p2ka.s: Error: `loc1@GLIBC_2.2.5' can't be versioned to common symbol 'loc1'
/tmp/ccD0p2ka.s: Error: `loc2@GLIBC_2.2.5' can't be versioned to common symbol 'loc2'
/tmp/ccD0p2ka.s: Error: `locs@GLIBC_2.2.5' can't be versioned to common symbol 'locs'
解決辦法:把misc目錄下的regexp.c做些修改
@@ -29,14 +29,18 @@ #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_23) -/* Define the variables used for the interface. */ -char *loc1; -char *loc2; +#include <stdlib.h> /* Get NULL. */ + +/* Define the variables used for the interface. Avoid .symver on common + symbol, which just creates a new common symbol, not an alias. */ +char *loc1 = NULL; +char *loc2 = NULL; + compat_symbol (libc, loc1, loc1, GLIBC_2_0); compat_symbol (libc, loc2, loc2, GLIBC_2_0); /* Although we do not support the use we define this variable as well. */ -char *locs; +char *locs = NULL; compat_symbol (libc, locs, locs, GLIBC_2_0);
把如上代碼保存為reg.patch文件
然后修改regexp.c文件:patch ./glibc-2.23/misc/regexp.c < ./reg.patch
(4)我在ubuntu 20 總不能編譯成 glibc-2.23,於是我在ubuntu 16 編譯了glibc-2.23,打包拷貝到ubuntu 20 然后解壓
三、測試
現在我們不使用默認的libc,而是用剛剛安裝的libc來編譯一個程序,看看有沒有安裝成功:
寫一個簡單的程序:
#include<stdio.h> #include<unistd.h> #include<stdlib.h> int main(){ puts("hello world!"); char * s1=malloc(0x20); read(0,s1,0x10); return 0; }
我們使用指定的libc來編譯:
gcc -g -L /home/zq/Desktop/glibc-2.31/64/lib -Wl,--rpath=/home/zq/Desktop/glibc-2.31/64/libs -Wl,-I /home/zq/Desktop/glibc-2.31/64/lib/ld-2.31.so hello.c -o hello
我們現在去調試,程序里有malloc這個函數,我們就看一下它的源代碼:
gdb hello
b malloc
r
但是我們做pwn題的時候,一般沒有源代碼,只是一個elf文件
當靶機libc版本和我們本地機器上libc版本不同的時候,就需要加載指定的libc,比如2.27 、2.31等
還是剛才那個程序,默認libc去編譯它:gcc hello.c -o hello1
我們用ida看一下它是怎樣尋找libc的,這里出現了ld-linux-x86-64.so.2的路徑,估計會通過它,找到待加載的libc.so
我們試着把這個路徑換為,我們期望加載的libc對應的ld-linux.so.2所在的目錄,本來是想把它換為絕對路徑(/home/zq/Desktop/glibc-2.31/64/lib/ld-linux-x86-64.so.2),但是好像行不通,於是縮減字符個數,換為相對路徑
我們把elf文件挪到 /home/zq/Desktop/glibc-2.31/64 ,然后相對路徑就是 ./lib/d-linux-x86-64.so.2 。
用ida去patch:
如果patch之后,運行報錯: No such file or directory
可以使用這個工具來patch:https://github.com/NixOS/patchelf
在hello1文件所在目錄(即/home/zq/Desktop/glibc-2.31/64)寫個腳本,看能不能正常調試:
from pwn import * sh=gdb.debug("./hello1") sh.interactive()
我們在read函數下斷點,看下read的源代碼:
再看一下堆塊的情況:
程序加載了libc-2.31.so