Tiny mach-0 are fun

I suppose I’m just not good with this kind of things, e.g. maintaining a blog.

Anyways, this post is about something easy and fun. I was asked about a tiny hello-world mach-o and since it was actually at least a year from last time I’ve been playing with a mach-o file it felt like a very good excuse for playing with them once again.

First thing I did was to go over to www.osxbook.com. I was pretty sure Amit Singh would have wrote a tiny mach-o already, and that was the case.

Downloaded tiny.asm and started from this phrase “There are plenty of zeros lurking in there.”.

  1. LC_SEGMENT segnames must be padded to 16 bytes, we can actually use that space for storing few opcodes (there must be at least a null termination after segname)
  2. we can use registers from LC_UNIXTHREAD for storing initial values we might need in order to avoid using bigger opcodes

That’s all, and it gives us a 180 bytes valid/working hello-world mach-o, which is, pretty small.
I think it’s still possible to have even a smaller one, but it would probably be >=10.8 only.

You can grab sources here.

Or have a quick look here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
;
; yasm -f bin rev_mach-o.asm
; it's tiny.asm from http://osxbook.com/blog/2009/03/15/crafting-a-tiny-mach-o-executable/
; with very few modifications in order to have both a valid and working hello-world mach-o
;
; http://twitter.com/__rev
;

BITS 32
        org   0x1000

        db    0xce, 0xfa, 0xed, 0xfe       ; magic
        dd    7                            ; cputype (CPU_TYPE_X86)
        dd    3                            ; cpusubtype (CPU_SUBTYPE_I386_ALL)
        dd    2                            ; filetype (MH_EXECUTE)
        dd    2                            ; ncmds
        dd    _ep2 - _text                 ; cmdsize
        dd    0                            ; flags
_text:
        dd    1                            ; cmd (LC_SEGMENT)
        dd    56                           ; cmdsize | sizeof(segment_command) makes it valid
        db    "T"                          ; segname
        db    0                            ; segname padding
_ep:
        ; SYS_write
        push  msg_size                     ; this is part of segname padding
        push  msg
        push  ecx
        push  ebx
        int   0x80

        ; - SYS_exit
        push  ebx
        jmp   _ep2

        dd    0x1000                       ; vmaddr
        dd    0x1000                       ; vmsize
        dd    0                            ; fileoff
        dd    filesize                     ; filesize
        dd    7                            ; maxprot
        dd    5                            ; initprot
        dd    0                            ; nsects
        dd    0                            ; flags

        dd    5                            ; cmd (LC_UNIXTHREAD)
        dd    80                           ; cmdsize
        dd    1                            ; flavor (i386_THREAD_STATE)
        dd    16                           ; count (i386_THREAD_STATE_COUNT)
        dd    4, 0, 1, 0, 0, 0, 0, 0       ; state
        dd    0, 0, _ep, 0, 0, 0, 0, 0     ; state
_ep2:
        mov   eax, ecx
        int   0x80

filesize equ  $ - $$

msg db 'Hello world', 0ah
        msg_size equ $ - msg

Thanks:

  • Amit Singh for his tiny.asm
  • Orlando for suggesting me that “__TEXT” segname is not really needed/enforced

References:

On MacOS 10.7 dyld randomization

First article for the blog, let’s talk about something I had in mind for a while.
There has been a lot of talk about the introduced full ASLR on MacOS X Lion, so as soon as I had my hands on the OS I wanted to check which were the changes introduced.

Let’s start from the very beginning, Mach-O. In order to understand what are the differences introduced in Lion, we need to first give a look at a Mach-O built on two different OSes, we will take as a reference Snow Leopard. Let’s build this simple code for test:

1
2
3
4
5
int main()
{
  while (1) {}
  return 0;
}

If we compile that code on Lion, no specific option passed to gcc, we will notice a difference from the very same code compiled on Snow Leopard. The difference is the presence of the flag MH_PIE (Position Independent):
Continue reading

Hello world!

Welcome to my new blog! I decided it was time to give real life to this website since I never really cared too much :) But hey, things change!

I will make this the first place where I’ll post all the stuff I usually do – software engineering, reverse engineering, OS internals and everything else worth publishing here.

I think that’s all for now :)