Skip navigation.

exploreopera

| Help

Sign up | Help

taviso

linux, programming and security

Posts tagged with "Programming"

Quick Security Auditing Puzzle

, , ,

Here's an interesting problem, how can I make this simple program crash? (assume IA32)

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    int a, b;

    if (argc != 3)
        return 1;

    a = atoi(argv[1]);
    b = atoi(argv[2]);

    return b ? a / b : 0;
}


scroll down for the solution.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.


The code correctly checks for divide by zero, so attempting this wont work:

$ ./a.out 42 0; echo $?
0
$


But not every invalid operation has been checked, while every programmer knows to avoid dividing by zero, very few are aware that it's also illegal to divide INT_MIN by -1. The reason is obvious, on a twos complement system |INT_MIN| is one greater than INT_MAX, so the result of the operation simply cannot fit in an integer.

This little known fact is almost guaranteed to crash any system that uses integer division on user controlled values as so few developers check for this unusual case.

$ ./a.out -2147483648 -1; echo $?
Floating point exception (core dumped)
136


Trace-p crackme

,

I wrote a crackme over the weekend and submitted it to crackmes.de, it's called trace-p for reasons that will be obvious to anyone who examines it :smile: The crackme focuses on anti-debugging and anti disassembler tricks rather than complex validation routines, so if you can defeat them it will probably not take you long to solve.

You can download the crackme here, if you can solve it (you need to write a keygen) you can submit your solution. I've decided to release the source code once a solution has been published in the hope of encouraging more people to write crackmes for linux.

Executable Patching with GDB

, ,

Patching code using gdb is no fun at all, if you need to do anything more complicated than just nop'ing a few instructions the standard procedure is to write the code, assemble it, objdump it then use ht or biew or similar to do the patching. You can patch code within gdb, but it's so long winded I'm sure few people bother unless they just need to modify one or two opcodes.

Someone mentioned that gentoo's skel .gdbinit file contained a handy macro `assemble` that would print opcodes to stdout, I normally use gdb vanilla so hadnt tried it before, but after checking it out, it's a great idea.

gdb> nasm_assemble 
Hit Ctrl-D to start, type code to assemble, hit Ctrl-D when done.
It is recommended to start with
        BITS 32
Note that this command uses NASM (Intel syntax) to assemble.
BITS 32
xor eax, eax
rdtsc
xor eax, edx
rol eax, 0x4
 31 c0 0f 31 31 d0 c1 c0 04

Unfortunately it has a number of problems:

  • It's buggy, you have to hit ctrl-d before starting, then again to finish, this is just confusing.
  • You have to enter "BITS 32" before entering any code, if you forget, you have to start again.
  • You can't see which instructions correspond to which bytes in the output.
  • It's not very gdb like, which normally allows you to finish by entering 'end' and uses readline.
  • You still have to patch the code manually using the bytes it outputs.


I rewrote the macro to fix all these issues. Here's an example of it in use.

$ gdb -q
(gdb) file true
Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) tb main
Breakpoint 1 at 0x80489b9: file true.c, line 62.
(gdb) r
main (argc=1, argv=0xbfffea64) at true.c:62
(gdb) x/6i $pc
0x80489b9 <main+21>:    mov    eax,DWORD PTR [ebx]
0x80489bb <main+23>:    mov    DWORD PTR [esp],0x6
0x80489c2 <main+30>:    mov    DWORD PTR [esp+4],0x8049e43
0x80489ca <main+38>:    mov    ds:0x804b884,eax
0x80489cf <main+43>:    call   0x80486e0 <setlocale@plt>
0x80489d4 <main+48>:    mov    DWORD PTR [esp],0x8048a79
(gdb) help assemble
Assemble instructions using nasm.
Type a line containing "end" to indicate the end.
If an address is specified, insert instructions at that address.
If no address is specified, assembled instructions are printed to stdout.
(gdb) assemble 
Instructions will be written to stdout.
Type instructions, one per line.
End with a line saying just "end".
>xor eax, eax
>inc eax
>end
00000000  31C0              xor eax,eax
00000002  40                inc eax
(gdb) assemble $pc
Instructions will be written to 0x80489b9.
Type instructions, one per line.
End with a line saying just "end".
>xor eax, eax
>inc eax
>mov ebx, 42
>int 0x80
>end
(gdb) x/6i $pc
0x80489b9 <main+21>:    xor    eax,eax
0x80489bb <main+23>:    inc    eax
0x80489bc <main+24>:    mov    ebx,0x2a
0x80489c1 <main+29>:    int    0x80
0x80489c3 <main+31>:    inc    esp
0x80489c4 <main+32>:    and    al,0x4
(gdb) c

Program exited with code 052.

This is really great for patching routines on the fly, if a hostile binary is using the classic ptrace(PTRACE_TRACEME, ...) trick to detect debuggers using ptrace(), patching it out is now as simple as:

$ cat test.c 
#include <unistd.h>
#include <sys/ptrace.h>
#include <stdio.h>

int main(int argc, char **argv)
{
   if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) == -1) {
       fprintf(stdout, "debugger present.\n");
       return 1;
   }

   fprintf(stdout, "no debugger present.\n");

   return 0;
}
$ gdb -q
(gdb) file ptrace
Using host libthread_db library "/lib/tls/libthread_db.so.1".
(gdb) r
debugger present.

Program exited with code 01.
(gdb) set write
(gdb) file ptrace
(gdb) info functions ptrace
0x080482f4  ptrace@plt
(gdb) assemble 0x080482f4
Instructions will be written to 0x80482f4.
Type instructions, one per line.
End with a line saying just "end".
>xor eax, eax
>ret
>end
(gdb) set write off
(gdb) file ptrace
(gdb) r
no debugger present.

Program exited normally.
(gdb) q

You can use convenience variables (eg registers), symbol names or actual addresses as an argument, and the address is checked for validity before prompting for input.

$ gdb -q
(gdb) assemble 0x12345
Cannot access memory at address 0x12345
(gdb) q


The prompt is supposed to be identical to the multiline prompt gdb uses, it also uses readline so you can use standard readline bindings, and you no longer have to use BITS 32. I'm really pleased with how it worked out, hopefuly somebody else will find it useful. Here's the full code of the macro:

define assemble
 # dont enter routine again if user hits enter
 dont-repeat
 if ($argc)
  if (*$arg0 = *$arg0)
    # check if we have a valid address by dereferencing it,
    # if we havnt, this will cause the routine to exit.
  end
  printf "Instructions will be written to %#x.\n", $arg0
 else
  printf "Instructions will be written to stdout.\n"
 end
 printf "Type instructions, one per line.\n"
 printf "End with a line saying just \"end\".\n"
 if ($argc)
  # argument specified, assemble instructions into memory
  # at address specified.
  shell nasm -f bin -o /dev/stdout /dev/stdin \
    <<< "$( echo "BITS 32"; while read -ep '>' r && test "$r" != end; \
                do echo -E "$r"; done )" | hexdump -ve \
        '1/1 "set *((unsigned char *) $arg0 + %#2_ax) = %#02x\n"' \
            > ~/.gdbassemble
  # load the file containing set instructions
  source ~/.gdbassemble
  # all done.
  shell rm -f ~/.gdbassemble
 else
  # no argument, assemble instructions to stdout
  shell nasm -f bin -o /dev/stdout /dev/stdin \
    <<< "$( echo "BITS 32"; while read -ep '>' r && test "$r" != end; \
                do echo -E "$r"; done )" | ndisasm -i -b32 /dev/stdin
 end
end
document assemble
Assemble instructions using nasm.
Type a line containing "end" to indicate the end.
If an address is specified, insert instructions at that address.
If no address is specified, assembled instructions are printed to stdout.
Use the pseudo instruction "org ADDR" to set the base address.
end

algebraic syntax assembly

,

We really need a free software algebraic syntax assembler, I've recently discovered a proprietaty language called terse that you'll love if you ever need to use assembly language in any of your projects.

terse is a free-form assembly language that makes assembly code more structured and recognisable, and also frees you from the annoying task of inventing new labels every 5 lines (my pet hate). I'm currently getting familiar with terse, but it's a pleasure to write compared to any standard assembly syntax, without sacrificing any of the power. Here's a hello world in terse:

segment .data;
    'msg = ("hello world",0ah);
segment .text;
global _start;
_start:
    eax = 4; 
    ebx = 1;
    ecx = $msg;
    edx = 12; !80h;
    &eax+; &ebx; !80h;

$ terse hello.t 
ÄÄÄÄÄÄÄ The terse (tm) Compiler, Version 2.20 ÄÄÄÄÄÄÄ
Copyright (C) Jim Neil 1989-1997, All Rights Reserved

    12 Lines In.
    14 Lines Out.

$ nasm -f elf -o hello.o hello.asm
$ ld -o hello hello.o
$ ./hello 
hello world

And an example of a loop:

section .data;
    'msg = ("loop #x", 0ah);
section .text;
global _start;
_start:
    ecx = 9;
    ebx = 1;
    edx = 12;
    edi === [$msg + 6];
    {   =ecx;
        ecx + '0';
        [edi] = cl;
        eax = 4; ecx = $msg; !80h;
        ecx=; 
    }-<>;
    &ebx; &eax+; !80h;

And here's a quick example of an insertion sort I wrote just to demonstrate the syntax:

section .data;
    'msg = ("arr[%d] = %d", 0ah, 00h);
    'arr = (34, 126, 42, 9, 124, 64, 24, 76, 98, 121);
section .text;
global _start;
extern printf;
_start:
    ebx = ecx = edx = eax = 0; eax+;
    {   bl = [arr+eax];
        cl = al; cl-;
        {   ecx ? --;    
            dl = [arr+ecx]; 
            dl - bl ? > {    
                [+ecx+arr] = dl; 
                ecx--;      
            }, { . };
        }.;                 
        [+ecx+arr] = bl;    
        eax+;               
        eax - 10 ?;
    }<>;
    ecx = 9;
    {   &eax; 
        al = [ecx+arr];
        =eax; =ecx; =msg; =.printf;
        ecx=; ecx=; eax=; ecx-;
    }++;
    &eax+; &ebx; !80h;

Unfortunately the compiler isnt free, so I've been considering designing my own algebraic assembly, perhaps using bison. Although I'd take some inspiration from terse, I think I would prefer a more c-like syntax where that's possible.

crackmes: hacker puzzles

, ,

crackmes are small reverse engineering puzzles designed to test your binary analysis skills and showcase interesting protection schemes, similar to those used in commercial software to validate registered users. Solving them can be tough, but must be the most fun you can have with a debugger.

The goal is usually to study how the crackme works and then write a keygen or disable the protection by patching the code (if permitted by the rules), and then publish a solution explaining how you solved it to anyone else interested in learning about it.

Some knowledge of assembly is all that's required to get started, but all sorts of skills are needed to solve the tougher crackmes, from cryptanalysis, algorithm analysis, reconstructing high-level code, executable unpacking, identifying and eliminating anti-debugger and anti-disassembler tricks, and so on.

The best site for finding linux crackmes is crackmes.de, where there's a whole community of users interested in reverse engineering, unfortunately the number of linux crackmes is tiny in comparison to the number of windows crackmes, however, there are still plenty of interesting ones available. The crackmes range from the ridiculously simple to some really tough projects that can take weeks to solve.

An example of the best of linux crackmes is one of my favourite authors, crp-, who has released three very different crackmes on crackmes.de. I've just published my solution to his third crackme, and really enjoyed it.

crp-'s crackmes are here, here and here.

If you're looking for an interesting project and would like to hone your debugging, reverse engineering or hostile binary analysis skills I would highly reccommend trying out a few crackmes.