Wednesday, December 31, 2014

Practical Reverse Engineering p.17 #4

Question number 4 on page 17 of Practical Reverse Engineering is as follows:

In all of the calling conventions explained, the return value is stored in a 32-bit register (EAX). What happens when the return value does not fit in a 32-bit register? Write a program to experiment and evaluate your answer. Does the mechanism change from compiler to compiler?

Here is a C function which returns a value that is a 128-bit struct:

struct toolong {
    int a;
    int b;
    int c;
    int d;
};

struct toolong get_toolong()
{
    struct toolong t;

    t.a = 0xDABBAD00;
    t.b = 0xDEADBEEF;
    t.c = 0xBADF00D;
    t.d = 0xBA5EBA11;

    return t;
}

Here is what happens when it is compiled with: gcc -O3 -m32

; GCC 4.8.2

get_toolong:
    mov    eax, dword ptr [esp+0x4]
    mov    dword ptr [eax], 0xdabbad00
    mov    dword ptr [eax+0x4], 0xdeadbeef
    mov    dword ptr [eax+0x8], 0xbadf00d
    mov    dword ptr [eax+0xc], 0xba5eba11
    ret    0x4

It is obvious that the return value of EAX is actually a pointer. The returned struct is stored on the stack.

The compiler for Microsoft Visual Studio 2013 produced essentially the same assembly, but with a full function frame. It was compiled with: /GS- /Gd /Gy /Ox

; MSVC 17.00.60610.1

get_toolong:
    push    ebp
    mov     ebp, esp
    mov     eax, [ebp + 8]
    mov     dword ptr [eax], 0DABBAD00h
    mov     dword ptr [eax + 4], 0DEADBEEFh
    mov     dword ptr [eax + 8], 0BADF00Dh
    mov     dword ptr [eax + 0Ch], 0BA5EBA11h
    pop     ebp
    retn

Notice that the GCC compiler stores the struct at [ESP + 4] and MSVC at [EBP + 8]. This means space needs to be pre-allocated by the caller for each.

Practical Reverse Engineering p.17 #3

Question number 3 on page 17 of Practical Reverse Engineering is as follows:

In the example function, addme, what would happen if the stack pointer were not properly restored before executing RET?

addme:
    push ebp
    mov ebp, esp
    movsx eax, word ptr [ebp+8]
    movsx ecx, word ptr [ebp+0Ch]
    add eax, ecx
    mov esp, ebp
    pop ebp
    retn

In this case, the ESP register is not modified at all (through mathemetical operations or PUSH/POP), so does not need to be properly restored.

In most cases however, without a MOV ESP, EBP instruction in the function prologue, you would return to an address that is whatever data happens to be in the current stack pointer at the time. This can often mean a crash, or at the very least unexpected behavior.

Practical Reverse Engineering p.17 #2

Question number 2 on page 17 of Practical Reverse Engineering is as follows:

Come up with at least two code sequences to set EIP to 0xAABBCCDD.

One sequence would be to push that address and then return.

push 0xAABBCCDD
ret

Another sequence would be to simply jump to the address.

jmp 0xAABBCCDD

You could also call the address.

call 0xAABBCCDD

Practical Reverse Engineering p.17 #1

Question number 1 on page 17 of Practical Reverse Engineering is as follows:

Given what you learned about CALL and RET, explain how you would read the value of EIP? Why can’t you just do MOV EAX, EIP?

You can't do MOV EAX, EIP because the instruction pointer is not readily accessible, likely as a security feature.

Here is one way you can get EIP (after the call) into another register.
_start:
    call geteip
    ; ...

geteip:
    pop eax       ;eax = eip (_start + sizeof(call))
    ; push eax 
    ; ret

Tuesday, December 30, 2014

Practical Reverse Engineering p.11 #1

Question number 1 on page 11 of Practical Reverse Engineering is as follows:

1. This function uses a combination SCAS and STOS to do its work. First, explain what is the type of the [EBP+8] and [EBP+C] in line 1 and 8, respectively. Next, explain what this snippet does.

mov edi, [ebp+8]
mov edx, edi
xor eax, eax
or ecx, 0FFFFFFFFh
repne scasb
add ecx, 2
neg ecx
mov al, [ebp+0Ch]
mov edi, edx
rep stosb
mov eax, edx

The first part of the question asks to define the types at [EBP+8] and [EBP+C].

For [EBP+8], we see it is moved into the EDI register a few instructions before REPNE SCASB. That instruction is generally used in string operations, in which EDI is the "destination index" of the operation. It is safe to assume that [EBP+8] is a byte buffer; the char* type.

Looking at [EBP+C], we see that it is moved into the AL register. This is an obvious hint to us that the value is a single byte; the char type.

So just by deducing the types and seeing their context, we have a vague idea of what is going on. The first half of the code sets ECX to -1, EAX to the null byte, then repeats over the buffer until the null byte is found (decrementing ECX for each byte before the null byte). Two is then added to ECX, and the register is turned into a positive number.

In the end, the first part of the code is the length of the buffer before the null byte. It's an implementation of the strlen() function. The second part of the code uses REP STOSB, which copies the AL register to the EDI register ECX times. This is the memset() function.

Here is the function in C:

/* cdecl */ 
char *asm_func(char *buffer, char byte)
{
   memset(buffer, byte, strlen(buffer));
   return buffer;
}

Sunday, December 28, 2014

Hex/Binary Pebble Watchface

My girlfriend got me the Pebble Steel smart watch for Christmas. The watch runs on an ARM Cortex M3 with a modified FreeRTOS kernel (which is described more as a threading library than a traditional operating system).

When I get a device like this I always have to poke around the API and see what it has to offer. So I looked at the getting started guide and wrote an app that simply displays the time and date in hexadecimal and binary forms.


The API is in C, and you only have access to a subset of the standard library. For instance, instead of doing itoa() with a base of two to display the numbers as binary, I had to create the following monstrosity:

const char *bytebin(int n, int m, char *b, int l)
{
    for (b[0] = '\0'; m > 0 && l > 0; m >>= 1, --l)
        strcat(b, ((n & m) == m) ? "1" : "0");
  
    return b;
}

And this is how I use it:

    snprintf(binDateBuffer, sizeof(binDateBuffer), "%s/%s/%s", 
           bytebin(tick_time->tm_mon + 1, 0x8, binMon, 4), 
           bytebin(tick_time->tm_mday, 0x10, binDay, 5), 
           bytebin(tick_time->tm_year + 1900, 0x400, binYr, 11));

The development IDE is hosted in the cloud. You literally just type in some C code and press play. The web application then compiles it and uploads it to your phone which sends it to the watch via Bluetooth. This lets you jump right into developing without any setup.

Friday, December 26, 2014

Architecture Detection (x86 or x64) Assembly Stub

This stub is useful for combining both a 32-bit and 64-bit shellcode payload into a single shot. Knowing the distinction in architecture is important for many types of payloads. For instance, on Windows the Thread Information Block is in the FS segment register on x86, and is in GS on x64.

Here are 5 bytes you you can use to detect the architecture you're on:

_shellcode:

    xor ecx, ecx        ; set ecx to 0
    db 0x41             ; x86 opcode for: inc ecx

    loop x64_code       ; ecx now -1 in x64, we jmp

x86_code:
    ; use fs segment

    ; ret

x64_code:
    ; use gs segment

Those familiar with x64 assembly should recognize that the 0x40-0x50 range is often used as a prefix for an instruction.  We can use this subtle difference to confuse the processor. In this case, if running in x64, the inc ecx opcode becomes a prefix for the loop. The loop instruction decrements ecx by one, and if ecx is not equal to 0 it will jump to the given label.

I used db 0x41 instead of inc ecx in the source code, since nasm uses a modern 2-byte instruction to prevent this ambiguity when we actually want the 1-byte increment. Here are the different outputs, which clearly show what is going on:

x86

 
 "\x31\xc9"              /* xor    %ecx,%ecx */
 "\x41"                  /* inc    %ecx */
 "\xe2\x01"              /* loop   x64_code  */     <-- ecx = 0, no jmp

x64

 
 "\x31\xc9"              /* xor    %ecx,%ecx */
 "\x41\xe2\x01"          /* rex.B loop x64_code  */ <-- ecx = -1, jmp