ptrace實現內存代碼注入

一、背景

ptrace是Unix系列系統的系統調用之一。其主要功能是實現對進程的追蹤。對目標進程,進行流程控制,用戶寄存器值讀取&寫入操作,內存進行讀取&修改。這樣的特性,就非常適合,用於編寫實現,遠程代碼注入。大部分的病毒會使用到這一點,實現,自用空間注入,rip位置直接注入,text段與data段之間的空隙注入。

二、主要流程

實驗使用的方式是,直接rip位置代碼注入。注入的shellcode,主要實現,使用syscall,進行系統調用。調用mmap(),在目標進程的0x00100000地址位置,申請8192大小的內存空間,將指定的注入程序,注入到這申請的空間中。並且將rip調整至其entry入口地址。

  1. attach目標進程。
  2. 讀取user_reg,獲取rip的值。
  3. 將shellcode注入到rip位置。
  4. 使用PTRACE_CONT參數,恢復程序執行。
  5. 當shellcode執行完成mmap匿名內存空間申請成功後。發送int3中斷信號給追蹤進程。
  6. 將要注入的elf可執行文件open,並且read(注意read要64位對齊)到緩衝區。
  7. PTRACE_POKE將elf可執行文件寫入到被注入進程shellcode創建的內存空間上。
  8. 讀寫user_reg將rip設置到elf可執行文件的入口點,也就是:mmap申請內存的起始地址+phdr->entry。
  9. 使用PTRACE_CONT參數,恢復程序執行,完成注入。

三、代碼實現
GitHub : https://github.com/HotIce0/code_injection

  • code_injection.c 代碼注入的執行程序
  • inject_me.c 被執行遠程注入的程序
  • test.c 要注入elf可執行程序

四、重點

  1. gcc -fpie -pie 用於生產與位置無關的目標代碼。
  2. gcc -nostdlib 用於生成,不使用標準鏈接庫的代碼。
  3. #define WORD_ALIGN(x) ((x + 7) & ~7) 用於64位對齊。因爲,在64位的ptrace的文檔中說明,PTRACE_POKE && PTRACE_PEEK一次操作的內存大小是64位,使用malloc申請的內存空間如果不是64位的整數倍,可能會出現內存非法訪問。segement fault。
// Open specify ELF file.
fd = open(h.exec, O_RDONLY);
// Read file status.
if (fstat(fd, &st)) {
	perror("fstat");
	exit(-1);
}
h.mem = (u_int8_t *)malloc(WORD_ALIGN(st.st_size));

4.在injection_code()函數中,要使用write輸出到屏幕一段字符串,如果直接“mmap _”,這段數據將會存儲到strtab節中,這會導致,輸出時,無法正常顯示,因爲,strtab的數據並沒有寫入目標進程中。
所以,這裏我使用的是字符串數組,這樣存儲在棧中。

5.這裏並沒有採用常用的shellcode一樣的字節碼,而是,直接將編譯好的代碼,讀取,寫入到目標進程。計算函數的大小,也是通過,直接injection_code()下面的函數,減去injection_code。函數名即函數指針。

6.其中的block_print()函數,對功能實現是無用的,只是我調試代碼時編寫的。Elf64_Addr get_text_segment_addr_by_pid(pid_t pid) 這個函數是用於,如果代碼注入位置的是text段的起始位置時用到的。由於我是直接注入到rip所在位置,所以,就沒用到。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章