# kid vm (pwn 188p, 22 solved)
> Writing a vm is the best way to teach kids to learn vm escape.
## Analysis
### Wrap-around vulnerability in the guest memory allocator
When allocating guest memory, the subroutine 006F fails to check if the new request fits into available free space.
The only check implemented is 008F, that validates pre-existing usage:```006F alloc_memory    proc near006F                 push    ax0070                 push    bx0071                 push    cx0072                 push    dx0073                 push    si0074                 push    di0075                 mov     ax, offset aSize ; "Size:"0078                 mov     bx, 5007B                 call    write_bytes007E                 mov     ax, offset requested_size0081                 mov     bx, 20084                 call    read_bytes0087                 mov     ax, ds:requested_size008A                 cmp     ax, 1000h008D                 ja      short error_too_big008F                 mov     cx, ds:free_space_offset0093                 cmp     cx, 0B000h      ; heap size0097                 ja      short error_guest_memory_is_full0099                 mov     si, word ptr ds:allocated_count009D                 cmp     si, 10h00A0                 jnb     short error_too_many_memory00A2                 mov     di, cx00A4                 add     cx, 5000h       ; heap start00A8                 add     si, si00AA                 mov     ds:allocated_chunks[si], cx00AE                 mov     ds:allocated_sizes[si], ax00B2                 add     di, ax00B4                 mov     ds:free_space_offset, di00B8                 mov     al, ds:allocated_count00BB                 inc     al00BD                 mov     ds:allocated_count, al00C0                 jmp     short restore_registers00C2 ; ---------------------------------------------------------------------------00C200C2 error_too_big:00C2                 mov     ax, offset aTooBig ; "Too big\n"00C5                 mov     bx, 800C8                 call    write_bytes00CB                 jmp     short restore_registers00CD ; ---------------------------------------------------------------------------00CD00CD error_guest_memory_is_full:00CD                 mov     ax, offset aGuestMemoryIsFullPl ; "Guest memory is full! Please use the ho"...00D0                 mov     bx, 32h00D3                 call    write_bytes00D6                 jmp     short restore_registers00D8 ; ---------------------------------------------------------------------------00D800D8 error_too_many_memory:00D8                 mov     ax, offset aTooManyMemory ; "Too many memory\n"00DB                 mov     bx, 10h00DE                 call    write_bytes00E100E1 restore_registers:00E1                 pop     di00E2                 pop     si00E3                 pop     dx00E4                 pop     cx00E5                 pop     bx00E6                 pop     ax00E7                 retn00E7 alloc_memory    endp```
This can be exploited by performing 11 allocations of 0x1000 bytes each.At that point next allocation is at 0x5000 + 11 * 0x1000 = 0x10000, wrapping to 0 as guest operates on 16-bit registers.This allows for overwrite of guest code.
### Use-After-Free vulnerability in the host memory allocator
When deallocating host memory, the subroutine 0000000000000C8C includes option to skip `allocated_chunks` cleanup:```void __fastcall free_host_memory(__int16 mode, unsigned __int16 chunk_index){  if ( chunk_index <= 0x10u )  {    switch ( mode )    {      case 2:        free(allocated_chunks[(unsigned __int64)chunk_index]);        allocated_chunks[(unsigned __int64)chunk_index] = 0LL;        --g_alloc_count;        break;      case 3:        free(allocated_chunks[(unsigned __int64)chunk_index]);        allocated_chunks[(unsigned __int64)chunk_index] = 0LL;        allocated_sizes[(unsigned __int64)chunk_index] = 0;        --g_alloc_count;        break;      case 1:        free(allocated_chunks[(unsigned __int64)chunk_index]);        break;    }  }  else  {    perror("Index out of bound!");  }}```
This option is not reachable using original guest code.However given previous vulnerability, we can control it using following `vmcall`:```ax = 0x0101bx = modecx = chunk_index```
## Exploitation
1. Modify code executing in guest by exploiting wrap-around vulnerability in the guest memory allocator
   The purpose is to expose host vulnerabilities via specific combinations of `vmcall` parameters, that are not reachable using original guest code.
2. Leak the address of host `libc` by exploiting use-after-free vulnerability in the host memory allocator
3. Increase `global_fast_max` by exploiting use-after-free vulnerability in the host memory allocator to corrupt the unsorted bin freelist
   The purpose is to enable fastbin for the next step.
4. Allocate memory overlapping with `_IO_2_1_stdout_.vtable` by exploiting use-after-free vulnerability in the host memory allocator to corrupt the fastbin freelist
5. Overwrite `_IO_2_1_stdout_.vtable` to use new table referring `one gadget RCE`
   The referred gadget is called immediately on next `putchar`.
Full exploit is attached [here](exploit.py).