Difference between revisions of "Summerschool Aachen 2004/Malware Lab"

From C4 Wiki
Jump to: navigation, search
Line 45: Line 45:
 
           decompression scheme used in the other executable formats doesn't
 
           decompression scheme used in the other executable formats doesn't
 
           work here.
 
           work here.
 
+
 
           Instead we must use temporary decompression to disk. Interestingly -
 
           Instead we must use temporary decompression to disk. Interestingly -
 
           because of the good memory management of the Linux kernel - this
 
           because of the good memory management of the Linux kernel - this
Line 51: Line 51:
 
           will be no disk access at all if you have enough free memory as
 
           will be no disk access at all if you have enough free memory as
 
           the entire process takes places within the filesystem buffers.
 
           the entire process takes places within the filesystem buffers.
 
+
 
           A compressed executable consists of the UPX stub and an overlay
 
           A compressed executable consists of the UPX stub and an overlay
 
           which contains the original program in a compressed form.
 
           which contains the original program in a compressed form.
Line 57: Line 57:
 
           The UPX stub is a statically linked ELF executable and does
 
           The UPX stub is a statically linked ELF executable and does
 
           the following at program startup:
 
           the following at program startup:
 
+
 
             1) decompress the overlay to a temporary location in /tmp
 
             1) decompress the overlay to a temporary location in /tmp
 
             ...
 
             ...

Revision as of 16:08, 6 October 2004

Notes about Presentation

ELF Tools and others

Notes about Lab Session

more elf tools

  • elfsh - elf shell

small quiz

There is a really small quiz consisting of just one question here.

Documenting the Lab Session

The Quiz, Question 1

The perl scripts execute the system call with the number 4, sys_write(), supplying a file descriptor of "1", which denotes stdout, the standard address of the ELF header of the binary (probably the perl interpreter) being executed (increased by 1 to skip the leading 0x7f) and an output length of "3". The perl script outputs "ELF" on my Linux box.

The Quiz, Question 2

I found out that the "yourtoy" file was a UPX - compressed file pretty fast. But trying to uncompress it with the upx utility didn't succeed as the file seemed to be corrupt.
I then tried upx'ing two other files, creating hexdumps of them and then doing a "diff3" on the hexdumps. I noticed that there were some areas where the other files matched but differed from "yourtoy" so I tried overwriting the corresponding areas in "yourtoy" with a hexeditor with the values found in the other files, but this did not work out.
After that i downloaded the source code for upx and ucl (the library upx uses) and used ddd to debug upx. I traced through several function calls until I found the one that finally returned the information "this is not a valid upx file". That function just searched the to-be-uncompressed file for some magic string, which it didn't find in "yourtoy". I then had a look at the other files I had created to find out that those contained the string twice whereas "yourtoy" only contained it once and instead of a second occurence contained another magic string of bovine origin. I replaced that with the correct string and was finally able to uncompress "yourtoy".

-- Lutz Böhne

I too had no problem finding the UPX header information in the packed binary. I tried to understand the UPX header format in order to be able to find bugs in the yourtoy compressed executable. After starring at it for a while and not knowing why the four bytes I thought were the version number were not at all what I expected, I tried to find the origin of the NotPackedException (btw. you only get it if you do a "upx -d yourtoy"). But after like five files of C++ code I can only barely read I gave up about this. I then upx'ed another binary and compared it to the provided one in order to find differences. But I only had a look at the top of the file b/c that's where I thought the header resided. Of course I had no luck with this either, so I jumped back into the source, finally finding a comment which explained the file layout. Now that I knew I had to look at the bottom, things were pretty straightforward. By changing only three bytes you could make the UPX file actually behave like it was supposed to...

-- Ernest Hammerschmidt


I did things a bit different. When I noticed that *someone* had messed up the upx header (or is it footer ?) I tried to look for documentation on the upx site. I didn't find any decent documentation on their site and didn't feel like looking at the source code because experiece has told me that such a thing can take a while (and we only have a couple of hours for the labsession). After some playing around with a hexeditor (to try and figure out what got changed) I got bored with the hexeditor and started looking at the manual file of upx. It said something interesting:

NOTES FOR LINUX/386

       How it works:

         Because Linux is a real operating system, the in-place in-memory
         decompression scheme used in the other executable formats doesn't
         work here.

         Instead we must use temporary decompression to disk. Interestingly -
         because of the good memory management of the Linux kernel - this
         often does not introduce a noticable delay, and in fact there
         will be no disk access at all if you have enough free memory as
         the entire process takes places within the filesystem buffers.

         A compressed executable consists of the UPX stub and an overlay
         which contains the original program in a compressed form.
         The UPX stub is a statically linked ELF executable and does
         the following at program startup:

           1) decompress the overlay to a temporary location in /tmp
           ...

Hm, so it gets decompressed in some temp file. To test this I made a test user and used the strace utility to see if this was true:

test@%m:%~% strace -i -s 10  ./yourtoy 
[????????] execve("./yourtoy", ["./yourtoy"], [/* 32 vars */]) = 0
[08048296] getpid()                     = 1664
[080482cf] open("/proc/1664/exe", O_RDONLY) = 3
[080482f1] lseek(3, 1468, SEEK_SET)     = 1468
[08048232] read(3, "\27\4`\341"..., 12) = 12
[08048351] gettimeofday({1097073253, 115757}, NULL) = 0
[0804837c] unlink("/tmp/upxBXX3ARQABUA") = -1 ENOENT (No such file or directory)
[0804839d] open("/tmp/upxBXX3ARQABUA", O_WRONLY|O_CREAT|O_EXCL, 0700) = 4
[080483aa] ftruncate(4, 15996)          = 0
[080483bc] old_mmap(NULL, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40000000
[08048232] read(3, "|>\0\0\315"..., 8)  = 8
[08048232] read(3, "\177?d\371"..., 5837) = 5837
[0804846d] write(4, "\177ELF\1\1"..., 15996) = 15996
[0804858b] unlink("/tmp/upxBXX3ARQABUA") = 0
[08048590] _exit(134518160)             = ?
test@%m:%~%

Aha ! so it just gets uncompressed and stored in some file in /tmp. I then fired up my debugger, set a breakpoint at 0x08048589 (right before the unlink()) and ran it. at this point it was uncompressed and not deleted yet. Then I ran file to see if that is the real binary:

test@%m:%~% ls -alhp *upxB* -rwx------ 1 test users 16K Oct 6 12:39 upxBXX3ARQABUA test@%m:%~% file upxBXX3ARQABUA upxBXX3ARQABUA: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), not stripped test@%m:%~%

I found what I needed to solve the second question. hooray :)

-- Ilja van Sprundel