Welcome to the new Woodmann RCE Messageboards Regroupment
Please be patient while the rest of the site is restored.

To all Members of the old RCE Forums:
In order to log in, it will be necessary to reset your forum login password ("I forgot my password") using the original email address you registered with. You will be sent an email with a link to reset your password for that member account.

The old vBulletin forum was converted to phpBB format, requiring the passwords to be reset. If this is a problem for some because of a forgotten email address, please feel free to re-register with a new username. We are happy to welcome old and new members back to the forums! Thanks.

All new accounts are manually activated before you can post. Any questions can be PM'ed to Kayaker.

RCE exercise for beginners

A classroom run by newbies for newbies. Gain valuable reversing experience & skills as we explain the in's and out's of RCE.
niaren
Member
Posts: 70
Joined: Thu Dec 10, 2009 3:16 pm

RCE exercise for beginners

Post by niaren »

Beginners will maybe find this difficult and I assume experienced reversers find this simple and uninteresting.
Attached is a small exe. The exe is very simple it prints one line to the console. The exe has been edited in a hex editor in such a way that you will see, if you open it in your favorite disassembler, the code obfuscated right at the entry point.

Problem 1: Why does the code appear obfuscated in a disassembler (only tested with IDA)? what is the idea?
Problem 2: How does it work?

To be honest, I don't think I understand completely every detail of how it works myself :)
Attachments
hello.zip
(674 Bytes) Downloaded 159 times
User avatar
Darkelf
Posts: 222
Joined: Wed Jan 24, 2007 7:20 pm

Post by Darkelf »

Hmmm,

I tried really hard, but I can't see any obfuscation.
The code is short (well the function to get the length of the string could be really shorter), simple and there is nothing hidden in the exe.
I least I don't see anything like that.
This is what I see:

Code: Select all

00011000     PUSH hello.00013000      ; ASCII "Hey, this actually works."
00011005     CALL hello.00011014
0001100A     PUSH 0
0001100C     CALL <JMP.&kernel32.ExitProcess>
00011011     INT3
00011012     INT3
00011013     INT3
00011014     PUSH EBP
00011015     MOV EBP,ESP
00011017     ADD ESP,-0C
0001101A     PUSH -0B
0001101C     CALL <JMP.&kernel32.GetStdHandle>
00011021     MOV DWORD PTR SS:[EBP-4],EAX
00011024     PUSH DWORD PTR SS:[EBP+8] ; hello.<ModuleEntryPoint>
00011027     CALL hello.00011050              ; call to a function that returns the length of the string
0001102C     MOV DWORD PTR SS:[EBP-C],EAX
0001102F     PUSH 0                           ; structure (not needed here - hence 0)
00011031     LEA EAX,DWORD PTR SS:[EBP-8]
00011034     PUSH EAX                         ; buffer
00011035     PUSH DWORD PTR SS:[EBP-C]        ; length of string
00011038     PUSH DWORD PTR SS:[EBP+8]        ; the string
0001103B     PUSH DWORD PTR SS:[EBP-4]        ; handle for stdout
0001103E     CALL <JMP.&kernel32.WriteFile>
00011043     MOV EAX,DWORD PTR SS:[EBP-8]   ;bytes written
00011046     LEAVE
00011047     RETN 4
0001104A     INT3
0001104B     INT3
0001104C     INT3
0001104D     INT3
0001104E     INT3
0001104F     INT3
00011050     MOV EAX,DWORD PTR SS:[ESP+4]       ; ntdll.7C920228
00011054     LEA EDX,DWORD PTR DS:[EAX+3]
00011057     PUSH EBP
00011058     PUSH EDI                                        ; ntdll.7C920228
00011059     MOV EBP,80808080
0001105E     MOV EDI,DWORD PTR DS:[EAX]
00011060     ADD EAX,4
00011063     LEA ECX,DWORD PTR DS:[EDI+FEFEFEFF]
00011069     NOT EDI                                               ; ntdll.7C920228
0001106B     AND ECX,EDI                                           ; ntdll.7C920228
0001106D     AND ECX,EBP
0001106F     JNZ SHORT hello.000110AA
00011071     MOV EDI,DWORD PTR DS:[EAX]
00011073     ADD EAX,4
00011076     LEA ECX,DWORD PTR DS:[EDI+FEFEFEFF]
0001107C     NOT EDI                                               ; ntdll.7C920228
0001107E     AND ECX,EDI                                           ; ntdll.7C920228
00011080     AND ECX,EBP
00011082     JNZ SHORT hello.000110AA
00011084     MOV EDI,DWORD PTR DS:[EAX]
00011086     ADD EAX,4
00011089     LEA ECX,DWORD PTR DS:[EDI+FEFEFEFF]
0001108F     NOT EDI                                               ; ntdll.7C920228
00011091     AND ECX,EDI                                           ; ntdll.7C920228
00011093     AND ECX,EBP
00011095     JNZ SHORT hello.000110AA
00011097     MOV EDI,DWORD PTR DS:[EAX]
00011099     ADD EAX,4
0001109C     LEA ECX,DWORD PTR DS:[EDI+FEFEFEFF]
000110A2     NOT EDI                                               ; ntdll.7C920228
000110A4     AND ECX,EDI                                           ; ntdll.7C920228
000110A6     AND ECX,EBP
000110A8    JE SHORT hello.0001105E
000110AA    TEST ECX,8080
000110B0     JNZ SHORT hello.000110B8
000110B2     SHR ECX,10
000110B5     ADD EAX,2
000110B8     SHL CL,1
000110BA     SBB EAX,EDX                                            ; ntdll.KiFastSystemCallRet
000110BC     POP EDI                                                ; kernel32.7C817077
000110BD     POP EBP                                                ; kernel32.7C817077
000110BE     RETN 4
000110C1     INT3
000110C2     JMP NEAR DWORD PTR DS:[<&kernel32.ExitProcess>]        ; kernel32.ExitProcess
000110C8     JMP NEAR DWORD PTR DS:[<&kernel32.GetStdHandle>]       ; kernel32.GetStdHandle
000110CE     JMP NEAR DWORD PTR DS:[<&kernel32.WriteFile>]          ; kernel32.WriteFile
I hope I didn't miss the point.

Regards
darkelf
User avatar
Kayaker
Posts: 4179
Joined: Thu Oct 26, 2000 11:00 am

Post by Kayaker »

For me it looks like this in Olly. I don't know why that first call doesn't resolve like you got, Darkelf.

Code: Select all

00011000 > $ 68 00300100    PUSH hello2.00013000   ;  ASCII "Hey, this actually works."
[B]00011005     E8             DB E8
00011006   . 0A000000       DD 0000000A[/B]
0001100A   . 6A 00          PUSH 0                                   ; /ExitCode = 0
0001100C   . E8 B1000000    CALL <JMP.&kernel32.ExitProcess>         ; \ExitProcess

In IDA:

Code: Select all

.text:B9961000                   start:
.text:B9961000 68 00 30 01 00                    push    13000h
.text:B9961005 E8 0A 00 95 B9                    call    near ptr [B]732B1014h[/B]
.text:B996100A 6A 00                             push    0
.text:B996100C E8 B1 00 00 00                    call    ExitProcess

This is kind of interesting, not the "obfuscation" per se (a literal interpretation by the disassembler of E8 - Call near, relative, displacement relative to next instruction), but how the base relocations are implemented by the loader.

Unlike the more usual occurence where the preferred load address is lower than the actual (relocated) load address, this is the opposite situation. So the base relocation "delta" value is apparently subtracted rather than added to the offset to get the correct displacement.

Here is an article describing how to force a relocation by setting the preferred base address to any invalid user-mode address (as niaren has done ;)

http://uninformed.org/index.cgi?v=6&a=3&p=2


I think this is a good little project to explore the workings of the Relocation Table, just going to leave it at that for now. ;)
User avatar
Darkelf
Posts: 222
Joined: Wed Jan 24, 2007 7:20 pm

Post by Darkelf »

Kayaker wrote:For me it looks like this in Olly. I don't know why that first call doesn't resolve like you got, Darkelf.

Code: Select all

00011000 > $ 68 00300100    PUSH hello2.00013000   ;  ASCII "Hey, this actually works."
[B]00011005     E8             DB E8
00011006   . 0A000000       DD 0000000A[/B]
0001100A   . 6A 00          PUSH 0                                   ; /ExitCode = 0
0001100C   . E8 B1000000    CALL <JMP.&kernel32.ExitProcess>         ; \ExitProcess
Oops, actually it looked that way in my Olly too.
I didn't count that as obfuscation since I come across this in Olly once in a while. So I almost automatically marked that area, did a right-click->binary copy->right-click again->binary paste - and all was well. I think it's quite common in Olly that code looks like this, especially when dealing with packed programms, but also with "normal" applications from time to time. I'm sorry if I confused anyone.
Thank you, Kayaker for the link. It looks like a good reading and I really need to learn more on this topic.

Regards
darkelf
aqrit
Member
Posts: 54
Joined: Sun Sep 14, 2008 3:25 pm

Post by aqrit »

to de-obfuscation this with olly use the "Remove analysis from selection" option
niaren
Member
Posts: 70
Joined: Thu Dec 10, 2009 3:16 pm

Post by niaren »

Thanks Darkelf, Kayaker and aqrit for participating in this 'exercise' and for showing some interest. I hope you had some fun and learned something. At least I did :)

Kayaker, it is fascinating to witness how much you can squeeze out of an exe when just a few bits have been flipped ;) As you already have guessed you hit the bulls eye with that link. Couldn't be more right on.

I don't think more people will post here so let me then end this by explaining, using my own words, how this relocation trick works and also outline how that exe was modified from the original.

I was searching for info about relocations when I found the paper Kayaker references above. I decided to experiment a little by going through the accompanying code and use it to modify my own exe. I recommend doing this because there is quite much to read between the lines in that paper which will be clear when trying out the trick on a real exe. Anyway, I thought that a good way to share this would be to make a very simple exe file with a few 'obfuscated' places in and post it here.

If an exe file has a preferred image base address in the high end of the memory map, then the windows loader relocates the exe file to an address in the low end of the memory map. The trick works because it is possible to predict that the image will be relocated to address 0x00010000 just as you see in the Olly dumps above. If a different address is chosen for some reason then the exe will crash. Just to repeat what Kayaker already have mentioned then the loader computes a Delta value as the difference between expected image base address and the preferred image base address. The Delta value is added to addresses in the image that are absolute because those addresses are not correct after the image is relocated. Those places are specified in the .reloc section. It is then possible to take advantage of the fact that we know that the loader will add the Delta value to the places specified in the .reloc section. This can be used to make the image look obfuscated when the exe is loaded at its preferred image base address and this is what you see in IDA.

So if
- an exe file has a preferred image base address in the high end of the memory map (trick does not work on dlls because it is hard to predict the expected image base address)
- the exe file looks like garbage when opened in a disassembler
- the exe looks fine when opened in a debugger
- and there is no unpacking stub to see

Then there is a pretty good chance that the relocation trick is used to 'pack' the file. If you want to see the trick used to its full potential then just open the challenge.exe file that comes with the paper :)

The hello.exe file comes from the masm32 tutorials. It is the first console tutorial (demo1). First the exe was modified using the code from the paper to rebase the code at a high end preferred image base address (I believe this could also have been achieve using some linker option). The exe file has 4 addresses that needs to be updated with the Delta value after relocation. This can most easily been seen by doing dumpbin /relocation hello.exe at the prompt.
Dump of file hello.exe

File Type: EXECUTABLE IMAGE

BASE RELOCATIONS #4
1000 RVA, 10 SizeOfBlock
1 HIGHLOW
C4 HIGHLOW
CA HIGHLOW
D0 HIGHLOW

Summary

1000 .data
1000 .rdata
1000 .reloc
1000 .text

As you can see RVA 1001 is going to be updated with the Delta value, this what 1 HIGHLOW means. Hello.exe was then modified by
- changing "1 HIGHLOW" to "6 HIGHLOW"
- changing manually the dword at RVA 1001 to 13000 which we know will be correct after relocation.
- changing dword at RVA 1006 by subtracting the Delta value, the loader will add it back again :)
Darkelf:
Thank you, Kayaker for the link. It looks like a good reading and I really need to learn more on this topic.
If you're interested I have an idea for another mini-project based on the same paper (my middle name is 'lets-do-a-mini-project' :) ). It seems that relocations can be used to manipulate control flow of an exe. Just look at section A.6 in the paper. It is possible to overwrite the return address of the loader. Because I'm having my hands full already in another mini-project you would have to take the initiative. I would very much like to participate and support you the best I can :)
User avatar
evaluator
Posts: 1539
Joined: Tue Sep 18, 2001 2:00 pm

Post by evaluator »

letz 5% "ruin" your wishes: W9x system will relocate exefile to 0400000.

new tip: you can make more then one relocator for same offset.
do work on this new :P-roject
User avatar
evaluator
Posts: 1539
Joined: Tue Sep 18, 2001 2:00 pm

Post by evaluator »

more wierd puzzle for you:
can you duplicate PE-header as one of PE-section?!?!
niaren
Member
Posts: 70
Joined: Thu Dec 10, 2009 3:16 pm

Post by niaren »

Yes, there might be portability issues with this trick. If I remember correctly the author of paper mentions this.
evaluator wrote:more wierd puzzle for you:
can you duplicate PE-header as one of PE-section?!?!
Do you think it's possible? :)
User avatar
evaluator
Posts: 1539
Joined: Tue Sep 18, 2001 2:00 pm

Post by evaluator »

yes. i'm not giving impossible missions.

what did you tried?
niaren
Member
Posts: 70
Joined: Thu Dec 10, 2009 3:16 pm

Post by niaren »

evaluator wrote:more wierd puzzle for you:
can you duplicate PE-header as one of PE-section?!?!
Using my own words, is this what you mean:

Modify the relocation section part only of an exe such that when opened in IDA the PE header appears as being a section of the exe?

Can you make it more precise?
User avatar
evaluator
Posts: 1539
Joined: Tue Sep 18, 2001 2:00 pm

Post by evaluator »

i mean: duplicate MZPE-header as one of PE-section. (not related to RELOCs).
User avatar
BanMe
Posts: 515
Joined: Mon Oct 27, 2008 11:05 am
Location: Farmington NH

Post by BanMe »

is this at compile time??
No hate for the lost children;
more love for the paths we walk,
'words' shatter the truth we seek.
from the heart and mind of Me
me, to you.. down and across

No more words from me, to you...
Hate and love shatter the heart and Mind of Me.
For the Lost Children;For the paths we walk; the real truth we seek!
User avatar
evaluator
Posts: 1539
Joined: Tue Sep 18, 2001 2:00 pm

Post by evaluator »

no, manual.
add section & try..
niaren
Member
Posts: 70
Joined: Thu Dec 10, 2009 3:16 pm

Post by niaren »

Image
Image

[ATTACH]2390[/ATTACH]
[ATTACH]2391[/ATTACH]

You like?

PS

Code: Select all

import sys
import pefile

pe = pefile.PE('watermark1.exe')
pe.add_section("PEHeader",pe.header,0xC0000040)
pe.write(filename='watermark1_after.exe')
Attachments
watermark1_after.zip
(2.83 KiB) Downloaded 98 times
watermark1.zip
(2.79 KiB) Downloaded 104 times
Locked