<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    【技術分享】mruby字節碼逆向入門

    VSole2022-08-08 08:42:00

    mruby簡介

    mruby是一個Ruby語言的輕量級實現,mruby工作方式類似CPython,它可以將Ruby源碼編譯為字節碼,再在虛擬機中解釋運行。

    第一次碰到mruby字節碼是在DEFCON 2021 Finals,其中的barb-metal題目是mruby字節碼運行的模擬IoT固件。沒想到在幾個月后的第五空間線上賽又碰到了mruby逆向,于是總結了一下mruby字節碼的特性。

    mrb字節碼格式

    mruby實現的是基于寄存器的虛擬機,所有的opcode可以從opcode.h查看,mruby字節碼對寄存器按照函數參數、局部變量、臨時寄存器的順序進行分配。將mruby源碼clone到本地并編譯,在bin目錄下的mirb程序是一個交互式mruby解釋器,運行時加上-v參數,可以將解釋器生成的字節碼打印出來,方便理解。

    mruby 2.1.0 (2019-11-19)
    > def f(a,b)*     c=a+b
    *     d=a-b
    *     return c*d
    * end...
    irep 0x55c104345310 nregs=4 nlocals=2 pools=0 syms=1 reps=1 iseq=14local variable names:
      R1:_file: (mirb)   13 000 OP_TCLASS     R2   13 002 OP_METHOD     R3      I(0:0x55c104346290)   13 005 OP_DEF        R2      :f
       13 008 OP_LOADSYM    R2      :f
       13 011 OP_RETURN     R2   13 013 OP_STOP
    irep 0x55c104346290 nregs=9 nlocals=6 pools=0 syms=0 reps=0 iseq=36local variable names:
      R1:a  R2:b  R3:&  R4:c  R5:dfile: (mirb)   13 000 OP_ENTER      2:0:0:0:0:0:0
       14 004 OP_MOVE       R6      R1              ; R1:a   14 007 OP_MOVE       R7      R2              ; R2:b   14 010 OP_ADD        R6   14 012 OP_MOVE       R4      R6              ; R4:c   15 015 OP_MOVE       R6      R1              ; R1:a   15 018 OP_MOVE       R7      R2              ; R2:b   15 021 OP_SUB        R6   15 023 OP_MOVE       R5      R6              ; R5:d   16 026 OP_MOVE       R6      R4              ; R4:c   16 029 OP_MOVE       R7      R5              ; R5:d   16 032 OP_MUL        R6   16 034 OP_RETURN     R6
    

    首先從下面部分的字節碼可以看出,mruby函數用到的寄存器已經分配給了特定的變量使用,R1-R2用于參數a和b,R4-R5用于局部變量c和d,R6-R7為臨時寄存器。

    對于有多個操作數的指令,mruby總會先將操作數存入連續的寄存器里,然后將第一個寄存器編碼到字節碼內,例如上圖中的032 OP_MUL R6,實際上OP_MUL接受兩個寄存器,R6和R7,并且總是將相乘的結果存入R6中。再例如上方的f函數聲明部分:002 OP_METHOD R3 I(0:0x55c104346290)將f函數的指針放入R3,后面的005 OP_DEF R2 :f是把R(2+1),即R3中的函數指針聲明為R2中的名字,即:f。了解到這一特性之后就可以對mruby字節碼進行初步的逆向了。

    示例:DEFCON 2021 barb-metal

    這道題目是DEFCON 29決賽中的一道攻防題目,可以參考archive.ooo上的存檔。題目用mrubyc(mruby解釋器的另一種實現)跑了一個模擬IoT設備,該IoT設備有Alarm,Thermostat,Speaker等幾個組件,每個組件可以接受不同的命令,例如Thermostat組件存儲了一些溫度數據,可以用THERM read day friday/THERM set night monday 90之類的指令讀寫數據。

    對題目的service程序進行逆向分析,可以發現Alarm,Thermostat,Speaker這些組件的邏輯均是用C實現,并注冊為Ruby對象的成員函數。

    題目的payload.bin是mruby字節碼,除去前260字節的簽名后,開頭的magic bytes是RITE0006,找到對應的mruby版本是v2.1.0,編譯后用mruby -v -b payload.bin運行,dump出字節碼。

    下面是set_therm函數片段,用來處理THERM set指令:

          267 OP_MOVE     R7    R5        ; R5:date
          270 OP_GETIV    R8    @dayofweek
          273 OP_SEND     R8    :size    0
          277 OP_GT       R7    
    # 此處R7是輸入的date,R8是dayofweek數組長度,用來檢查輸入的星期是否溢出
    # OP_GT R7隱含了比較的對象R8
          279 OP_JMPNOT   R7    306    
    # 若R7<R8,跳轉到306,即通過驗證,未通過則向下走返回
          283 OP_LOADSELF R7        
          285 OP_STRING   R8    L(5)      ; "INVALID date "
          288 OP_MOVE     R9    R5        ; R5:date
          291 OP_STRCAT   R8    
          293 OP_STRING   R9    L(3)      ; ""
          296 OP_STRCAT   R8    
          298 OP_SEND     R7    :putsDBG    1
          302 OP_LOADNIL  R7        
          304 OP_RETURN   R7
    # 輸出字符串,提示越界
    # OP_SEND R7 :putsDBG 1隱含一個參數R8
          306 OP_GETIV    R7    @therm
          309 OP_MOVE     R8    R4        ; R4:time
          312 OP_MOVE     R9    R5        ; R5:date
          315 OP_MOVE     R10   R6        ; R6:temp
          318 OP_SEND     R7    :write    3
          322 OP_RETURN   R6              ; R6:temp
    # 驗證通過,調用設備函數
    # OP_SEND R7 :write 3中函數指針為R7,隱含3個參數R8-R10
    

    在mruby字節碼中,OP_GETIV R7 @therm即獲得Thermostat組件的對象,放入R7寄存器,OP_SEND R7 :write 3意為用R7后面的3個寄存器,即R8-R10中的值作為參數,調用R7對象的write函數,此處的write函數是C注冊的Thermostat組件的寫入功能(sub_112CBF)。

    這道題目的意思就是通過發送指令,由mruby程序對輸入的參數進行校驗,再傳給C函數完成相應操作。題目只允許對mruby字節碼進行patch,修補參數校驗中的漏洞。

    經過逆向分析可以發現THERM set指令的第一個參數可以是day/night,也可以直接輸入0/1,第二個參數星期也可以直接輸入數字0-6,而上面的函數片段顯示mruby只檢查了data\<dayofweek.size,即輸入的星期要小于7,沒有檢查下界,利用THERM set 0 -addr value可以實現越界寫。

    同樣在THERM get對應的get_therm函數中:

          238 OP_MOVE       R6    R5         ; R5:date
          241 OP_LOADI_0    R7        
          243 OP_LT         R6    
          245 OP_JMPIF      R6    256    
    # 判斷date是否小于0,若小于0檢查失敗
          249 OP_MOVE       R6    R4         ; R4:time
          252 OP_LOADI_1    R7        
          254 OP_GT         R6    
          256 OP_JMPNOT     R6    273    
    # 判斷time是否大于1,若大于1檢查失敗
          260 OP_LOADSELF   R6        
          262 OP_STRING     R7    L(4)       ; "INVALID date"
          265 OP_SEND       R6    :putsDBG   1
          269 OP_LOADNIL    R6        
          271 OP_RETURN     R6        
          273 OP_GETIV      R6    @therm
          276 OP_MOVE       R7    R4        ; R4:time
          279 OP_MOVE       R8    R5        ; R5:date
          282 OP_SEND       R6    :read     2
          286 OP_RETURN     R6
    

    對date參數的校驗只有下界沒有上界,可以造成越界讀,賽后參考源碼可以發現這里是出題人故意埋的漏洞。

    Alarm和Speaker組件中也有越界讀寫的漏洞,由于這道題mruby僅用來校驗參數,后面的攻擊就回到了普通的堆利用上,對這題的逆向分析就到此為止。

    實戰:第五空間線上賽 babyruby

    再次碰到mruby還是比較意外的,由于有了DEFCON的經驗,這次的babyruby做的比較順利,僥幸拿了全場唯一解。

    題目給的字節碼開頭是RITE0200,對應mruby v3.0.0,編譯運行并dump字節碼,程序的main函數位于底部,開頭先檢查flag{xxxx}格式,括號內的x共32字節。

    再翻一翻上面的字節碼,發現其中有不少有趣的函數:

    顯然后四樣操作是AES的組成部分,于是猜測題目是AES加密,開始尋找加密后的密文,以及加密用的密鑰。密文比較部分就位于整個程序的末尾:

          1796 OP_MOVE      R10     R14             ; R10:wanted
          1799 OP_JMP               2065
    # 這里是一個for循環開始的部分,首先跳轉到循環變量i的檢查
          1802 OP_GETCONST  R14     :Cipher
          1805 OP_SEND      R14     :new    0
          1809 OP_MOVE      R11     R14             ; R11:cipher
          1812 OP_MOVE      R14     R3      ; R3:content
          1815 OP_MOVE      R15     R4      ; R4:i
          1818 OP_SEND      R14     :[]     1
    # R14=content[i]
          1822 OP_MOVE      R15     R3      ; R3:content
          1825 OP_MOVE      R16     R4      ; R4:i
          1828 OP_ADDI      R16     16
          1831 OP_SEND      R15     :[]     1
          1835 OP_ADD       R14     R15
          ...
          2011 OP_MOVE      R12     R14             ; R12:cc
    # R14+=content[i+16],下面省略了一些取content數組元素的操作,
    # 最終的結果是用content[i,i+8,i+16,i+24]四字節組成一個14字節的字符串放在cc里
          2014 OP_MOVE      R14     R11             ; R11:cipher
          2017 OP_MOVE      R15     R12             ; R12:cc
          2020 OP_STRING    R16     L(2)    ; c*
          2023 OP_SEND      R15     :unpack 1
          2027 OP_SEND      R14     :hash   1
          2031 OP_MOVE      R13     R14             ; R13:output
    # output=cipher.hash(cc.unpack("c*"))
    # 將cc字符串unpack為bytes,再把bytes傳給cipher的hash函數
          2034 OP_MOVE      R15     R10             ; R10:wanted
          2037 OP_MOVE      R16     R4      ; R4:i
          2040 OP_SEND      R15     :[]     1
    # wanted=R4[i],R4即比較對象,下文有解釋
          2044 OP_SEND      R14     :!=     1
          2048 OP_JMPNOT    R14     2056
          2052 OP_LOADF     R14
          2054 OP_RETURN_BLK        R14
    # if(output!=wanted){return false;}
          2056 OP_MOVE      R14     R4      ; R4:i
          2059 OP_ADDI      R14     1
          2062 OP_MOVE      R4      R14             ; R4:i
    # i = i+1
          2065 OP_MOVE      R14     R4      ; R4:i
          2068 OP_MOVE      R15     R3      ; R3:content
          2071 OP_SEND      R15     :length 0
          2075 OP_LOADI_4   R16
          2077 OP_DIV       R15     R16
          2079 OP_LT                R14     R15
          2081 OP_JMPIF     R14     1802
    # if(i < content.length/8) goto 1802;
    # 循環變量i從0到content.length/8,每輪循環處理4字節
          2085 OP_LOADT     R14
          2087 OP_RETURN    R14
    # return true,flag正確
    

    題目將輸入的32字節分為8組,每組4個字節先擴展到14字節,再經cipher.hash函數處理后與R4數組的值進行比較,R4是一個8×64的二維數組,靜態編碼在mruby字節碼中,可以直接提取。

    cipher.hash函數是一個14字節到64字節的映射,起初我認為是AES加密,但AES128的特征是前9輪是完整的四樣操作,最后一輪是沒有MixColumns的三樣操作,我在程序中找不到僅有SubBytes,ShiftRows和AddRoundKey的尾輪操作,沒法證明AES的猜想。從cipher.hash函數的名字,以及輸出長度64字節,還有代碼中的一些padding操作,可以推斷這是Whirlpool)散列函數(Whirlpool是一種利用了AES的四種操作構造出的散列函數,其內部狀態是8×8的置換排列網絡。據我所知使用了AES的組件的算法有WhirlpoolARIASM4Rijndael-192Rijndael-256,這幾種算法都可以使用Intel AESNI進行加速,十分神奇)。

    由于每輪輸入僅4字節,可以直接對R4數組中散列的結果進行爆破,找出輸入:

    #include <openssl/whrlpool.h>#include <stdio.h>#include <string.h>const unsigned char h1[] = {    16,  87,  130, 164, 79,  211, 145, 230, 203, 8,   8,   147, 105, 87,  47,
        ... // 從字節碼中提取出R4數組};int main() {  int a, b, c, d;  int i;  char flag[32];  char buf[14];  memset(flag, 0xff, 32);  unsigned char md[64];  for (i = 0; i < 8; i++) {    printf("%d\n", i);    for (a = 0; a < 80; a++) {      for (b = 0; b < 80; b++) {        for (c = 0; c < 80; c++) {          for (d = 0; d < 80; d++) {
                buf[0] = a;
                buf[1] = c;
                buf[2] = c;
                buf[3] = b;
                buf[4] = d;
                buf[5] = c;
                buf[6] = a;
                buf[7] = c;
                buf[8] = a;
                buf[9] = c;
                buf[10] = b;
                buf[11] = c;
                buf[12] = d;
                buf[13] = c;
                WHIRLPOOL(buf, 14, md);            if (memcmp(md, h1 + 64 * i, 64) == 0) {              printf("%d good\n", i);
                  flag[i] = a;
                  flag[i + 8] = b;
                  flag[i + 16] = c;
                  flag[i + 24] = d;              goto done;
                }
              }
            }
          }
        }
      done:    printf("%d done\n", i);
      }  for (i = 0; i < 32; i++) {    printf("0x%02x,", flag[i]);
      }  return 0;
    }//[0x16, 0x27, 0x00, 0x35, 0x32, 0x16, 0x18, 0x15, 0x22, 0x21, 0x03, 0x1a, 0x1e, 0x1d, 0x3b, 0x1a,// 0x2d, 0x38, 0x0e, 0x03, 0x28, 0x08, 0x28, 0x0e, 0x2e, 0x31, 0x39, 0x3e, 0x04, 0x1d, 0x15, 0x23]
    

    然而這還不是這道題目的全部,爆破結果只是輸入cipher.hash的數組,在這之前該程序還對輸入有一些處理:

          081 OP_MOVE       R15     R3      ; R3:content
          084 OP_SEND       R15     :length 0
          088 OP_SUBI       R15     1
          091 OP_RANGE_INC  R14
    # R14=content[0:length-1],OP_RANGE_INC用R15創建range
          093 OP_BLOCK      R15     I(0:0x55d31260ff20)
          096 OP_SENDB      R14     :each   0
    # OP_BLOCK加載了一個lambda函數到R15中
    # 將這個lambda函數應用到R14的每個元素上,類似python的map函數
          100 OP_LOADI_1    R6              ; R6:step
          102 OP_LOADI_0    R4              ; R4:i
          104 OP_LOADI_0    R7              ; R7:lst
    # setp=1, i=0, lst=0,初始化一個復雜的循環
          106 OP_MOVE       R14     R4      ; R4:i
          109 OP_MOVE       R15     R6      ; R6:step
          112 OP_ADD        R14     R15
          114 OP_MOVE       R4      R14             ; R4:i
          117 OP_JMP                214
    # i+=step,循環開始
          120 OP_MOVE       R14     R3      ; R3:content
          123 OP_MOVE       R15     R7      ; R7:lst
          126 OP_SEND       R14     :[]     1
          130 OP_SEND       R14     :ord    0
          134 OP_MOVE       R8      R14             ; R8:c
    # c=ord(content[lst])
          137 OP_MOVE       R14     R7      ; R7:lst
          140 OP_ADDI       R14     1
          143 OP_MOVE       R15     R4      ; R4:i
          146 OP_SUBI       R15     1
          149 OP_RANGE_INC  R14
          151 OP_BLOCK      R15     I(1:0x55d31260fff0)
          154 OP_SENDB      R14     :each   0
    # 對[lst-1:i+1]范圍內的每個元素應用R15的lambda表達式
          158 OP_MOVE       R14     R8      ; R8:c
          161 OP_MOVE       R15     R7      ; R7:lst
          164 OP_ADDI       R15     1
          167 OP_SEND       R14     :^ 1
          171 OP_SEND       R14     :chr    0
    # R14=chr(c^lst)
          175 OP_MOVE       R15     R3      ; R3:content
          178 OP_MOVE       R16     R7      ; R7:lst
          181 OP_MOVE       R17     R14
          184 OP_SEND       R15     :[]=    2
          188 OP_MOVE       R14     R4      ; R4:i
          191 OP_MOVE       R7      R14             ; R7:lst
          194 OP_MOVE       R14     R6      ; R6:step
          197 OP_ADDI       R14     1
          200 OP_MOVE       R6      R14             ; R6:step
          203 OP_MOVE       R14     R4      ; R4:i
          206 OP_MOVE       R15     R6      ; R6:step
          209 OP_ADD        R14     R15
          211 OP_MOVE       R4      R14             ; R4:i
    # lst=i, step=step+1, i=i+step
          214 OP_MOVE       R14     R4      ; R4:i
          217 OP_MOVE       R15     R3      ; R3:content
          220 OP_SEND       R15     :length 0
          224 OP_LT         R14     R15
          226 OP_JMPIF      R14     120
    # if(i<content.length) goto 120; 否則循環結束
    

    content是輸入的32字節,循環過程中有一個lambda表達式較為復雜,通過靜態分析很難找出其中的操作,于是我采用了動態調試的方法猜出其中的處理邏輯。

    mruby動態調試

    上面的循環中有一個特別的opcode:149 OP_RANGE_INC R14,它為我們提供了一個完美的斷點位置,我們只需要找出mruby虛擬機中對OP_RANGE_INC的處理,斷在這里,再查看此時R3中的內容,就能看出輸入的32字節經過了什么樣的變換。解釋器主函數位于src/vm.c:

    首先準備調試環境:mruby的變量采用了類似Chromium V8的指針壓縮機制,參見mruby文檔中的MRB_WORD_BOXING,這一特性使得gdb查看mruby變量變得十分困難,好在編譯時可以選擇關掉該特性:

    export CFLAGS='-DMRB_NO_BOXING=1 -O0 -g' && make -j4
    

    編譯出帶調試信息的mruby解釋器,gdb斷點設在vm.c:2661,隨便輸入一個測試flag,比如flag{whosyourdaddyISEEDEADPEOPLE10086},這里故意避免輸入連續的01234或者abcd,為了方便猜測后面的處理究竟是異或還是加減乘除四則運算。

    過掉第一個斷點,第二次斷下時位于091 OP_RANGE_INC R14,查看一下mrb->c->ci->stack[3],即R3的內容:

    R3類型是MRB_TT_STRING,這個string就是content變量,即我們輸入的32字節。再把valuep成員轉換成RString,繼續深入查看:

    看到了我們的輸入存放的位置,此時繼續執行,進入循環,每次循環將該位置的內存dump下來:

    pwndbg> x/32xb ((struct RString*)mrb->c->ci->stack[3].value.p)->as.heap.ptr0x555555698655: 0x77    0x68    0x6f    0x73    0x79    0x6f    0x75    0x720x55555569865d: 0x64    0x61    0x64    0x64    0x79    0x49    0x53    0x450x555555698665: 0x45    0x44    0x45    0x41    0x44    0x50    0x45    0x4f0x55555569866d: 0x50    0x4c    0x45    0x31    0x30    0x30    0x38    0x36# 將字母數字從ASCII轉為對應的index0x555555698700: 0x3a    0x2b    0x32    0x36    0x3c    0x32    0x38    0x350x555555698708: 0x27    0x24    0x27    0x27    0x3c    0x12    0x1c    0x0e0x555555698710: 0x0e    0x0d    0x0e    0x0a    0x0d    0x19    0x0e    0x180x555555698718: 0x19    0x15    0x0e    0x01    0x00    0x00    0x08    0x06# content[0] ^= 10x555555698700: 0x3b    0x2b    0x32    0x36    0x3c    0x32    0x38    0x350x555555698708: 0x27    0x24    0x27    0x27    0x3c    0x12    0x1c    0x0e0x555555698710: 0x0e    0x0d    0x0e    0x0a    0x0d    0x19    0x0e    0x180x555555698718: 0x19    0x15    0x0e    0x01    0x00    0x00    0x08    0x06# content[1] ^= 2# content[2] ^= 2^content[1]0x555555698700: 0x3b    0x29    0x1b    0x36    0x3c    0x32    0x38    0x350x555555698708: 0x27    0x24    0x27    0x27    0x3c    0x12    0x1c    0x0e0x555555698710: 0x0e    0x0d    0x0e    0x0a    0x0d    0x19    0x0e    0x180x555555698718: 0x19    0x15    0x0e    0x01    0x00    0x00    0x08    0x06# content[3] ^= 4# content[4] ^= 4^content[3]# content[5] ^= 5^content[4]0x555555698700: 0x3b    0x29    0x1b    0x32    0x0e    0x01    0x38    0x350x555555698708: 0x27    0x24    0x27    0x27    0x3c    0x12    0x1c    0x0e0x555555698710: 0x0e    0x0d    0x0e    0x0a    0x0d    0x19    0x0e    0x180x555555698718: 0x19    0x15    0x0e    0x01    0x00    0x00    0x08    0x06# content[6] ^= 7# content[7] ^= 7^content[6]# content[8] ^= 8^content[6]# content[9] ^= 9^content[6]0x555555698700: 0x3b    0x29    0x1b    0x32    0x0e    0x01    0x3f    0x0a0x555555698708: 0x17    0x15    0x27    0x27    0x3c    0x12    0x1c    0x0e0x555555698710: 0x0e    0x0d    0x0e    0x0a    0x0d    0x19    0x0e    0x180x555555698718: 0x19    0x15    0x0e    0x01    0x00    0x00    0x08    0x06
    

    邏輯雖然難以描述,但是規律還是一目了然,在加上之前逆出的mruby字節碼邏輯,還是很容易猜出公式。該循環是一個異或的過程,每次處理1,2,3,4個字節,直到超出數組長度。

    寫出python還原輸入:

    a = [0x16, 0x27, 0x00, 0x35, 0x32, 0x16, 0x18, 0x15, 0x22, 0x21, 0x03, 0x1a, 0x1e, 0x1d, 0x3b, 0x1a,     0x2d, 0x38, 0x0e, 0x03, 0x28, 0x08, 0x28, 0x0e, 0x2e, 0x31, 0x39, 0x3e, 0x04, 0x1d, 0x15, 0x23 ]
    s = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'v = 1t = 1l = 0p = 0while True:
        a[p] ^= v    for i in range(l):
            a[p+1+i] ^= (v+i)
            a[p+1+i] ^= a[p]
        v += t
        t += 1
        p += 1 + l
        l += 1
        if l > 6:        breakprint('flag{{{}}}'.format(''.join(map(lambda x: s[x], a))))
    

    flag: flag{Nbdn7YVDrt8PQOzAtZMQsUW7eszx4TLZ}

    總結

    Ruby作為一種靈活的腳本語言,經常在CTF比賽中出現,Ruby的一種實現————mruby解釋器是基于寄存器的虛擬機,可以將Ruby代碼編譯為mruby字節碼。mruby的編譯器實現得比較簡單,沒有復制消除等優化過程,生成的字節碼可讀性很高,稍微靜下心來逆出程序的邏輯還是比較容易的。

    字節碼r15
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    mruby是一個Ruby語言的輕量級實現,mruby工作方式類似CPython,它可以將Ruby源碼編譯為字節,再在虛擬機中解釋運行。
    匯編語言是一種用于電子計算機、微處理器、微控制器或其他可編程器件的低級語言,亦稱為符號語言。Smali匯編基礎Smali語言最早是由JesusFreke發布在Google Code上的一個開源項目,并不是擁有官方標準的語言。因此也將Smali語言稱作Android虛擬機的反匯編語言。基本類型Smali基本數據類型中包含兩種類型,原始類型和引用類型。而在Smali中則是以LpackageName/objectName的形式表示對象類型。
    假如想在x86平臺運行arm程序,稱arm為source ISA, 而x86為target ISA, 在虛擬化的角度來說arm就是Guest, x86為Host。這種問題被稱為Code-Discovery Problem。每個體系結構對應的helper函數在target/xxx/helper.h頭文件中定義。
    BPF之路二(e)BPF匯編
    2021-12-28 16:18:32
    原始的BPF又稱之為class BPF(cBPF), BPF與eBPF類似于i386與amd64的關系
    tvm分析與還原
    2023-06-06 09:18:55
    把騰訊的安全產品拉入 PE 工具,看到區段中有.tvm0那就沒跑了。demo這次還原用到的demo是前段時間游戲安全技術競賽的決賽附加題一個非常好的demo,驅動基本上全vm了。還要特別感謝這位大佬放出來的脫殼版,給我節省了許多驗證還原效果的時間。pwd=ICEY)文檔我也只說明了一些明顯的點,還是看代碼更加清晰。然后給你的idapython安裝以下的庫:import capstone
    2021安洵杯PWN WP詳解
    2021-12-29 16:41:08
    做了2021安洵杯線上賽題目,總體來說題目有簡單有難的,難易程度合適,這次就做了pwn,把四道pwn題思路總結一下,重點是沒幾個人做出來的最后一道pwnsky,賽后做了復現。
    綠城杯-WriteUp
    2021-09-30 06:44:41
    Pwnnull解題思路說是null 其實是off by one,基于uaf那題,這里直接試著打2.23,用的libc也是和uaf那題一樣的#?ezuaf解題思路遠程doublefree泄漏cfree后三位,配合mallochook地址通過libcdatabase確定2.23,然后打og#?
    前言本文主要著眼于glibc下的一些漏洞及利用技巧和IO調用鏈,由淺入深,分為 “基礎堆利用漏洞及基本IO攻擊” 與 “高版本glibc下的利用” 兩部分來進行講解,前者主要包括了一些glibc相關的基礎知識,以及低版本glibc下常見的漏洞利用方式,后者主要涉及到一些較新的glibc下的IO調用鏈。
    交互式反匯編器,簡稱為IDA。是目前最棒的一個靜態反編譯軟件,為眾多0day世界的成員和ShellCode安全分析人士不可缺少的利器!此章節讓我們熟悉通過IDA修改參數、函數、返回值,同時詳細解讀標志位的概念,熟悉堆棧及詳細解讀ARM三級流水線概念和ARM編碼編譯為二進制的全過程。
    Adhrit是一款針對Android移動端操作系統的安全分析工具,該工具可以幫助廣大研究人員根據Ghera基準,深入執行滲透測試偵查階段的任務并進行靜態字節分析。Adhrit是一個開源的Android APK逆向工程和分析工具,旨在為移動安全測試的自動化實現提供有效的解決方案。Adhrit的構建注重靈活性和模塊化,并使用了Ghera基準來識別Android應用程序中的漏洞模式。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类