AFL-QBDI與AFL-Unicorn實戰


文章一開始發表在微信公眾號

https://mp.weixin.qq.com/s/wNeeuS3XojfZWvtAJ9xGlQ

Fuzz Android Native庫

為了能夠Fuzz Android Native庫,筆者基於QBDI框架為AFLplusplus新增一種Fuzz模式,代碼和文檔如下

https://github.com/vanhauser-thc/AFLplusplus/tree/master/qbdi_mode

qbdi_mode的工作方式是在template.cpp里面把目標庫加載到內存,然后設置好被測函數需要的參數,最后調用目標函數。在這個過程里面會使用QBDI的API獲取到目標程序的覆蓋率信息並啟動forkserver和AFL通信,從而實現Fuzz。

本節以Whatsapp為例,介紹如何Fuzz Android的Native庫。在Whatsapp APK中的libwhatsapp.so里面的Java_com_whatsapp_Mp4Ops_mp4check函數是一個JNI函數

__int64 __fastcall Java_com_whatsapp_Mp4Ops_mp4check(JNIEnv_ *a1, __int64 a2, __int64 a3, char a4)
{
  // 轉換UTF-8字符串到 C 字符串
  fpath = (a1->functions->GetStringUTFChars)(a1, v5, 0LL);
  clock_gettime(1, &tp);
  
  // 目標函數, 處理視頻文件
  v8 = sub_79C70(fpath, &tp, 2 * (v4 == 0), 0);

根據JNI函數的調用約定和Java層的參數信息可以發現該函數的參數類型大概為

a1: JNIEnv
a2: jobject
a3: 文件路徑
a4: 一個bool變量,為0或者1

Java_com_whatsapp_Mp4Ops_mp4check函數最終會把文件路徑轉換成C字符串並傳入sub_79C70函數,后面再也沒有用過這個文件路徑,那么這個函數應該就是實際處理文件的函數,而且函數的參數比較簡單,那么我們就可以直接去Fuzz這個函數,修改template.cpp在main函數里面獲取到sub_79C70函數的地址

	void *offset_func = dlsym(handle, "Java_com_whatsapp_Mp4Ops_mp4check");

	if (NULL == offset_func) {
		printf("getprocaddress error\n");
		return 1;
	}

	p_target_func = (target_func)((unsigned char *)offset_func + 0x45af0);
	printf("target function addr: %x\n", p_target_func);

然后修改fuzz_func,構造好sub_79C70函數需要的參數,然后調用它。

QBDI_NOINLINE int fuzz_func() {

  if (afl_setup()) { afl_forkserver(); }

  unsigned long len = 0;
  char *        data = read_file(FPATH, &len);

  printf("In fuzz_func\n");
	struct timespec tp;
	clock_gettime(1, &tp);
  p_target_func(FPATH, &tp, 1);
  printf("execute p_target_func:%p\n", p_target_func);
  exit(0);
  return 1;
}

編譯完成后要能夠執行被測程序需要先把libQBDI.so放到安卓設備上並設置LD_LIBRARY_PATH為libQBDI.so和libwhatsapp.so所在的路徑,因為libwhatsapp.so還依賴一些APK里面的庫。

# find / -name libwhatsapp.so 2>o
/data/app/com.whatsapp-wMSOMeRwydbzJJmi-G1wEw==/lib/x86_64/libwhatsapp.so
# ls ./libQBDI.so
./libQBDI.so
# pwd
/data/lsl
# export LD_LIBRARY_PATH=/data/lsl:/data/app/com.whatsapp-wMSOMeRwydbzJJmi-G1wEw==/lib/x86_64/
# ./loader /data/app/com.whatsapp-wMSOMeRwydbzJJmi-G1wEw==/lib/x86_64/libwhatsapp.so xxx.mp4
target function addr: 7eaf9c70
In fuzz_func
execute p_target_func:0x702f7eaf9c70

確保程序能夠正常執行后下面用AFL去Fuzz即可

./afl-fuzz -i mp4in/ -o mp4out -m 5000 -t 3000 -p exploit  -- ./loader /data/app/com.whatsapp-wMSOMeRwydbzJJmi-G1wEw==/lib/x86_64/libwhatsapp.so @@

image-20191124182515208

總結

本章介紹了各種Fuzz技術並介紹了一些優化Fuzz測試的方法,為了能夠熟練使用各種Fuzz技術,讀者需要多實踐並且要多看看Fuzz工具的源代碼。Fuzz測試並不是單純的啟動Fuzz工具讓Fuzz工具執行就可以的,在Fuzz的過程中測試人員需要不斷地查看Fuzz的狀態,一般而言Fuzz的流程如下

  1. 確定並分析Fuzz目標。
  2. 初步運行Fuzz工具保證能夠正常開始Fuzz。
  3. 收集大量初始用例並對初始用例去重。
  4. 用去重后的初始用例開始Fuzz。
  5. 在Fuzz過程中當代碼覆蓋率長時間沒有增長時,人工介入分析代碼覆蓋率,想辦法提升代碼覆蓋率。
  6. 對發現的Crash去重。

最后祝讀者能夠挖到更多的漏洞。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM