1) MD5 Code Autocheck

Playing with the Linker

Take a look:

extern void * _init;
extern void * _start;

char * end = "THIS TEXT MORE OR LESS WILL BE PLACED IN THE .rodata";

main(){
        char * c = (void *)&_init;
        printf(".init -----------------> is at: %p\n",c);
        printf(".text -----------------> is at: %p\n",&_start);
        printf("main ------------------> is at: %p\n",main);
        printf("end string inside rodata is at: %p\n",end);

        md5_state_t state;
        md5_byte_t digest[16];
        int di;

        md5_init(&state);
        md5_append(&state, (const md5_byte_t *)c , end - c);
        md5_finish(&state, digest);

        printf("MD5 = ");
        for (di = 0; di < 16; ++di)
            printf("%02x", digest[di]);
        printf("\n");
}
(autotest.c)

Simple, isn't it?

Let me explain what I'm trying to do here...

Download and unpack yaadt.1.tgz

  $ tar xvzf yaadt.1.tgz
yaadt.1/
yaadt.1/md5.c
yaadt.1/md5.h
yaadt.1/autotest.c

 $ cd yaadt.1

 $ gcc *.c

 $ objdump -h a.out

a.out:     file format elf32-i386

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .interp       00000013  08048154  08048154  00000154  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .note.ABI-tag 00000020  08048168  08048168  00000168  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .hash         0000002c  08048188  08048188  00000188  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .gnu.hash     00000020  080481b4  080481b4  000001b4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .dynsym       00000060  080481d4  080481d4  000001d4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynstr       00000054  08048234  08048234  00000234  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .gnu.version  0000000c  08048288  08048288  00000288  2**1
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .gnu.version_r 00000020  08048294  08048294  00000294  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .rel.dyn      00000008  080482b4  080482b4  000002b4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .rel.plt      00000020  080482bc  080482bc  000002bc  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 10 .init         00000017  080482dc  080482dc  000002dc  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 11 .plt          00000050  080482f4  080482f4  000002f4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 12 .text         000010a4  08048350  08048350  00000350  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 13 .fini         0000001c  080493f4  080493f4  000013f4  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
 14 .rodata       00000120  08049420  08049420  00001420  2**5
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 15 .eh_frame     00000004  08049540  08049540  00001540  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 16 .ctors        00000008  0804af0c  0804af0c  00001f0c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 17 .dtors        00000008  0804af14  0804af14  00001f14  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 18 .jcr          00000004  0804af1c  0804af1c  00001f1c  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 19 .dynamic      000000d0  0804af20  0804af20  00001f20  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 20 .got          00000004  0804aff0  0804aff0  00001ff0  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 21 .got.plt      0000001c  0804aff4  0804aff4  00001ff4  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 22 .data         00000010  0804b010  0804b010  00002010  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 23 .bss          00000004  0804b020  0804b020  00002020  2**2
                  ALLOC
 24 .comment      00000130  00000000  00000000  00002020  2**0
                  CONTENTS, READONL

Usually, in any executable, the pure machine code resides between the ".init" and ".fini" sections. Your code in particular is stored inside the ".text" section.
Read Only data such as Built-In Strings, are stored in the ".rodata" section.
Other variable variables usually are stored in the ".data" section.
(More infos are inside "Morgan-Kaufman's Linkers and Loaders")

Anyway;
Execute it: (colors are manually added)
  $ ./a.out
.init -----------------> is at: 0x80482dc
.text -----------------> is at: 0x8048350
main ------------------> is at: 0x80483f4
end string inside rodata is at: 0x8049428
MD5 = 56cd28e117177577a26c446b15f9493c
WOOOOOOOOOO!!! It's MAGIKKKK!!!

EH?
GCC (Build, Link) and Exec System Call memory mapping process

When the sources are built, in the linking process:
1) All the object pieces are correctly placed and ordered inside any relative section.
2) All the symbols (i.e. _init, _start, main, end, printf ...) are resolved.

When this file is executed:
1) First of all, all the previous defined sections are copyed in the relative Virtual Memory Area.
2) A call to .init is performed.

Hashing the code


Debug it: (colors are manually added)
  $ gdb ./a.out

GNU gdb 6.7.1
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-linux-gnu"...
(no debugging symbols found)
Using host libthread_db library "/lib/libthread_db.so.1".

(gdb) run
Starting program: /root/Eugenio/crypt/pubblicazione/yaadt.1/a.out
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)

.init -----------------> is at: 0x80482dc
.text -----------------> is at: 0x8048350
main ------------------> is at: 0x80483f4
end string inside rodata is at: 0x8049428
MD5 = 56cd28e117177577a26c446b15f9493c

Program exited with code 012.

 (gdb) break main
Breakpoint 1 at 0x8048402

(gdb) run
Starting program: /root/Eugenio/crypt/pubblicazione/yaadt.1/a.out
(no debugging symbols found)
(no debugging symbols found)
(no debugging symbols found)

Breakpoint 1, 0x08048402 in main ()

(gdb) c
Continuing.

.init -----------------> is at: 0x80482dc
.text -----------------> is at: 0x8048350
main ------------------> is at: 0x80483f4
end string inside rodata is at: 0x8049428
MD5 = 93dc018e7d235e3be7f11546ad26afa4

Program exited with code 012.
(gdb) quit

What's happen?
If you notice in the sourcecode, two pointers are used inside the MD5 (external) routine.
1) 0x80482dc -> _init
2)
0x8049428 -> end
The sections .init, .plt, .text, .fini, and a piece of .rodata are inside this range.

MD5[ _init --to--> end ] is performed.

So, any modification of my machine code or the static libraries machine code will change this MD5 Hash value.


MD5 Hash sum of the loaded bytecode


GDB and other Debuggers, use INT3 (0xcc)  substitution trick.
(http://www.alexonlinux.com/how-debugger-works)
So, if someone try to debug your executable, a different MD5 Hash value is calculated.
MD5 Hash sum of the debugged (modified) bytecode


< Previous - UP - Next >
ą
link.svg
(54k)
Eugenio Parodi,
6 Mar 2011, 23:27
ą
Eugenio Parodi,
6 Mar 2011, 23:27
ą
Eugenio Parodi,
6 Mar 2011, 23:28
ċ
yaadt.1.tgz
(5k)
Eugenio Parodi,
21 Feb 2011, 01:19
Comments