Log in

View Full Version : How to assemble a timer /w HIEW?


N8di8
April 23rd, 2006, 16:59
1.
I am an absolute newbie.

2.
I would like to assemble something like "invoke sleep, 500" and patch into an executable.

3.
I made some efforts but now I'm stuck and don't really know how to proceed. How can I "translate" invoke sleep into standard asm commands and which functions do I need to import?

4.
I asked a very similar question @ http://community.reverse-engineering.net/viewtopic.php?t=5164

Many thanks in advance for your help.

LLXX
April 23rd, 2006, 19:29
First you need to find where you want to invoke the code, then record the original instructions at that location and write a JMP to an empty area in the file. At that empty area you write back the instructions that the JMP overwritten and then add
Code:
push 500
call [kernel32.sleep]
You may also need to add an import for kernel32.sleep if the file does not already have one in its IAT, and update the sizes of the PE section so that it does load your extra code.

Admiral
April 23rd, 2006, 21:26
Like LLXX says, there's a quick way and a less quick way to do this. If you want to patch only for personal use then you'll almost certainly get away with hardcoding the address for Sleep:
Code:
PUSH 500
CALL 7C802442
(as of XP SP2)

But if you want to maintain version compatibility (past and future) with your operating system (in particular, kernel32.dll) then you'll have to do some research into the format of the IT and IAT, and use CALL DWORD PTR [IAT entry for Sleep] instead.

Regards
Admiral

N8di8
April 24th, 2006, 00:35
Many thanks. Will try this.

EDITED:

1.
The following things did not work with me: CALL 7C802442 or call [kernel32.sleep]

2.
I had to import sleep function from kernel32.dll (using Code Snippet Creator). IID King did not work with a compressed file.

@naides Thanks for the reminder.

naides
April 24th, 2006, 10:58
I doubt that this is critical, but if you want to sleep exactly 500 milliseconds you need to

PUSH 1F4

instead of

PUSH 500

N8di8
April 24th, 2006, 17:43
Ok..now that everything worked so fine I would like to try the next thing...

I would like to initialize and release winsock. According to (http://win32assembly.online.fr/asmsockguide.html) this should work as follows:

invoke WSAStartup, 101h,addr wsadata
invoke WSACleanup

Unfortunately, it's not entirely clear to me from which file I have to import WSAStartup & Cleanup (and how to assemble the above instructions)...

Admiral
April 24th, 2006, 21:41
Heh, good call naides. I guess it isn't safe to assume people are talking in hex, especially when their numbers are nice decimal fractions.

A quick Google says that WSAStartup (and obviously WSACleanup) comes from WS2_32.dll. MSDN is an excellent resource for this information.
As before, push the arguments onto the stack (in reverse order) before calling the function. If this isn't clear, take some time to read The Art Of Assembly Language Programming. It's an excellent (online) book.

We're happy to give you a push in the right direction, but you'll need to learn ASM at some point of you're to make it in this game.

Regards
Admiral

Kayaker
April 24th, 2006, 23:25
I had forgotten that Iczelion had all that winsock stuff. If you download the example code and other resources he provides you should have enough information to work with. The standard include files are wsock32.inc and wsock32.lib

http://win32assembly.online.fr/winsock.html

As for assembling all that, well um, I'm hoping that this combination of patch + winsock access isn't being used for some nasty online business, but that being said, if the patch is getting this complex you might as well use Icz's Code Snippet Creator itself. Adding dlls and imports, the assembly itself and even the patching can all be taken care of in the simplest manner possible. Writing, debugging and modifying the patch is no different from writing MASM with any other editor. If you need guidance search the Project forum for projects we had using 'Code Snippet Creator'.

Kayaker

LLXX
April 24th, 2006, 23:28
Quote:
[Originally Posted by Admiral] If this isn't clear, take some time to read The Art Of Assembly Language Programming. It's an excellent (online) book.
The book isn't that good... I've read most of it and IMHO it seems to be more of an advertisement for the author's own "assembler" (which isn't really an assembler either), which has a completely different syntax than the normal assemblers (further confusing beginners) and I can honestly say his example code isn't any better than what a compiler would produce. Except for the small section on machine architecture, everything else deviates significantly from the norm. I even wonder if the title was chosen to add deliberate ironic emphasis to the content

My recommendation: Iczelion's Win32assembly tutorials.

N8di8
April 25th, 2006, 00:59
Thank you for the hints. I will try this out (will take some time ;-).

@Kayaker I promise that this patch will not be used for some nasty online business. For the time being, I just want to initialize & release winsock. (Otherwise I would simply have asked how to patch a loadlibrary [nasty dll] into a browser or the like ;-)

N8di8
April 25th, 2006, 17:13
I'm stuck again

1.
I decided not to add imports with the help of IID King or Code Snippet Generator. This is because it seems to me that the imports are added to a new section or something like that. In any way, this is not a "clean" solution but some kind of a "hack". (I am afraid that the entire file might be considered a virus by the heuristics of a virus scanner.)

2.
Consequently, I decided to use a file which is compressed with UPX (level 1). According to PE Editor the relevant imports (sleep etc.) were left alone by UPX.

3.
The message box tutorial says: "The last thing we need is the so-called opcode for MessageBox function. To get this opcode we use the little program Opgen by NeuRaL_NoiSE. You can also find it out in WDasm or Hiew by looking a bit around." Unfortunately, neural noise does not properly run on my computer. Seems to be a problem with the resources. Is there any equivalent to neural noise? Alternatively, how do I figure out the opcode of the sleep function? PE Editor says that the sleep function is located at a certain offset (but this is only the offset where I can find a string called sleep).

4.
I have already set a new entry point. But my instructions push 500, call 004147B0 point somewhere to nirvana (that's also what Ollydbg tells me when I debug the file).

Many TIA

Admiral
April 25th, 2006, 21:32
1. It's altogether possible to use a PE editor/dumper to rebuild an IT with a few extra imports that you can overwrite the existing one with. This way, there will be nothing at all suspicious about your binary. Another idea would be to use the leftover space in one of your image sections (and the same idea in the physical image) to add a bound imports descriptor, assuming one isn't already used. This way you won't have to move anything around. This one takes a little more planning though.

2. I'm not sure that I understand how using a compressor helps your cause. In fact, I'm not sure that I have a clue what your cause is .

3. There's really no need to use specific tools to assemble these days. OllyDbg has all the assembly power you'll need. Find your way to the spot where you want to assemble (in the disassembly window) and hit the space bar. Olly has a good idea what it is you want to do most of the time and it has the added bonus of understanding many contextual symbols, and being able to patch directly to disk without the bother of using a hex editor.
For example, if you tell it to assemble 'CALL Sleep', it will glark the kernel32 prefix and will assemble the necessary offset for Sleep. The problem here is that it will assemble to address numerically, without visiting the IAT you've worked so hard to modify. So the trick is to explicitly tell it where the IAT entry is:

4. I'm guessing 'CALL [4147B0]' is what you're after (if 4147B0 is the location of the address of Sleep in your IAT). Notice the square brackets. The fact that it's a DWORD pointer you're after is implicit.
'CALL 4147B0' won't do it, as this sets EIP to 4147B0, not to the DWORD at that address. The difference is subtle but all-important.

By the way, as naides pointed out, your PUSH should be 1F4, not 500. As it stands, you're sleeping for 1.28 seconds.

Regards
Admiral

N8di8
April 26th, 2006, 01:32
@Admiral

Many thanks.

1.
Rebuilding an IT sounds quite interesting. However, that's probably still too difficult for me. I may try this later on.

2.
Square brackets...ieek. I will try this. Thanks for the hint! I did not know about the syntax.

What I still not understand is the following. If I open a UPX compressed (level 1) file with PE Editor I can view the imports. (This is different if I compress it with level 9. Then most imports are gone.) PE Editor says that, for example, the function sleep can be found at a certain offset. If I look at the file with a HIEW I can see that (very close) this offset there is a string "sleep". How does this help to perform the instruction sleep? I understand the sleep function can be used if the respective .dll is mapped into the process memory space of the executed file. I would have thought that PE Editor tells me the address at which the sleep function begins (and not merely the location of the string sleep). What's the relation between the string and the address @ which the sleep function's instructions begin?

3.
Ollydbg ... I will also try to use this program. Too bad that I just familiarized myself with HIEW ;-)

4.
I got naides' message. But the exact timing is not important. Actually, I use sleep 5000 (not only 500).

5.
My foremost cause is to learn this stuff. My secondary cause is innovative & relates to a specific target (but has nothing to do with software cracking).

Regards.

Admiral
April 26th, 2006, 08:44
5. Don't worry too much about the cracking thing even if you are. Lots of our members are part of cracking groups and it's generally tolerated. Just as long as you don't post target-specific code (along with the name) or get involved with malware/spam everybody's happy.

3. Don't dispose of HIEW just yet. It's a decentish hex editor & disassembler. OllyDbg does much of what HIEW can but its primary function is as a debugger. They are two tools used for different jobs and both of them are used by many reversers.

2. The location of the string 'Sleep' in an exe could be one of many things. It's possible that this is just part of the string-table (in .rsrc) or a hardcoded-string (in .text or .data/.rdata). Often enough though, it will be surrounded by the names of other API functions (in one of the .#data sections). If this is the case, it is most likely part of the PE's import table (IT). At load-time, the operating system parses this structure, as directed in the PE header. It will use these strings along with the guts of LoadLibraryA and GetProcAddress (specifically LdrLoadDLL and LdrGetProcedureAddress) to load all the necessary DLLs and fill the import address table (IAT) with the appropriate addresses. You can actually watch the system doing this from within a usermode debugger if you wish. This way, the code can be assembled with all calls running via the IAT. If then for some reason, at load time, the DLL has to be mapped to an unexpected location, Windows needs only set the new address in the IAT for everything to work. This is the purpose of the IAT - to allow DLLs to be mapped arbitrarily without needing to patch several pieces of code.
The easiest way to find out the location of the IAT entry for a mapped function is to find a CALL to it and note down which pointer it is calling. If you can run to (or set EIP at) this CALL, your debugger will do the work of calculating the offset. Your 4147B0 (wherever it came from) seems like a fairly convincing place for an IAT entry.

As for your UPX query: The range of compression levels in UPX are a tradeoff between file size and performance. If a PE imports a lot of DLL functions, it will have a fairly large IT, containing many plaintext names. This is something of a waste of space and is a good candidate for compression. However, if the IT is compressed, Windows won't be able to parse it and so UPX will have to uncompress and process this manually on startup. This makes for a performance hit, and so it is not done in the lighter compression levels.
For this reason, the IT will be Windows (and hence PE Editor) readable only if UPX (or another compressor) hasn't touched it.

Regards
Admiral

N8di8
April 26th, 2006, 17:43
1.
I highly appreciate your help.

2.
I did "For example, if you tell it to assemble 'CALL Sleep', it will glark the kernel32 prefix and will assemble the necessary offset for Sleep." with Ollydbg.

I noted the offsets and accordingly modified the file with HIEW. (I used HIEW because I was unable to figure out how to save the changes made with Olly.)

I used an UPX level 1 compressed file so that the required imports were available. I changed the OEP and inserted a JMP from the new EP to the old one.

Everything worked fine. Until I tried to execute the file on a machine with Windows XP SP1 (instead of SP2) ...

2.
I guess that I did exactly what you described ("The problem here is that it will assemble to address numerically, without visiting the IAT you've worked so hard to modify.": I hardcoded the address of the sleep function which is different under the SP1 .dll.

3.
Consequently, I tried to figure out "where the IAT entry is" and miserably failed

Although "The easiest way to find out the location of the IAT entry for a mapped function is to find a CALL to it and note down which pointer it is calling." I have problems to do so. Firstly, I am not sure how (with the help of Ollydbg?) to find a call to it and, morever, I doubt that this function is used at all. (Is it possible that this is a "redundant" import which is not actually used?).

4.
Are you aware of a good Ollydbg tutorial so that I can better familiarize myself with the tool?

Many many thanks

Admiral
April 26th, 2006, 19:18
4. It wouldn't be my place to direct you to a good OllyDbg tut, as I haven't used one for the longest time. There are hundreds out there though. Maybe somebody else will have a recommendation.

2. I still don't understand why you need to use UPX at all. You can patch any PE as you like without needing to compress it.
To save a patch to disk in OllyDbg, highlight the code that you have modified, right-click, 'Copy to executable', 'Selection'. When you close the window that appears you will be prompted to save. This will be your patched file.

1. You're welcome

3. Two points; the first one is just for completeness.

3a. To find the position of a specific function in the IAT, you can do the following:
First find the bounds of the IAT: Locate any CALL DWORD PTR DS:[<&dll.fn>]. This DWORD pointer is almost certainly inside your IAT. For example:

00451211 FF15 18974A00 CALL DWORD PTR DS:[<&kernel32.GetVersion>]

You can extract the numerical address from the opcode. FF15 is 'CALL DWORD PTR', and 18974A00 is the little-endian DWORD for the IAT pointer. Split this into bytes and reverse the order to get 004A9718 (i.e. convert to big-endian). Now this address is firmly inside this target's IAT. If you 'Goto' this address within the dump window (in 16 byte hex mode), you'll see a bunch of dwords, many of them starting with 77 or 7C. This is your IAT. Use your head to work out where it starts (often 1000 aligned) and where it ends (two nulls in a row, if the IAT is intact).
Now to find where a given function pointer lives inside this IAT, you can simply perform a memory search (in the dump window) over the appropriate range. Find out the address of Sleep, pad it out with zeros into a DWORD, reverse the bytes as before and hit the search button. The rest should be obvious.

However, you say that Sleep isn't imported in your target. You can verify this using your PE editor - if it doesn't appear under kernel32's thunk then indeed, you'll have to rethink. As before, you can inject a reference into your IT and let Windows take care of the rest, but this is tricky when you have no nicely-placed data-caves to work with. So I propose a couple of alternatives:

3b. Perhaps it's a little irresonsible of me to throw the deep end at you, but if you don't want to mess about with the IT, you can get the address of Sleep manually:
If your target imports the function GetProcAddress then you're in luck. If not, you may want to get UPX to use a higher compression level, because if UPX does compress the IAT, it will need to import GetProcAddress (in its own IAT) to finish the job.
Once you have access to GetProcAddress and GetModuleHandleA (which I'd imagine it will import for you too), you can simply get your EP patch to grab the address of Sleep on the fly:
Code:

PUSH 0 ; Terminating null
PUSH 6C6C642E ; ASCII ".dll"
PUSH 32336C65 ; ASCII "el32"
PUSH 6E72656B ; ASCII "kern"
PUSH 0 ; Terminating null
PUSH 70 ; ASCII "p"
PUSH 65656C53 ; ASCII "Slee"
LEA EDX, DWORD PTR SS:[ESP+C]
PUSH EDX ; Push "kernel32.dll"
CALL DWORD PTR DS:[<GetModuleHandleA>] ; Get the base of kernel32.dll
PUSH ESP ; Push "Sleep"
PUSH EAX ; Push Kernel32.dll
CALL DWORD PTR DS:[<GetProcAddress>] ; Get the address of Sleep
ADD ESP, 1C ; Remove strings from the stack
MOV DWORD PTR DS:[xxxxxxxx], EAX ; Save the address of Sleep

This snippet will get the address of Sleep for you on the fly and save it into xxxxxxxx (which you should set to be some null in the IAT, perhaps). All you need to do is fill in the IAT locations of GetModuleHandleA and GetProcAddress. I've encoded the names (of Sleep and Kernel32.dll) as DWORDS - this is what all those PUSHes are.

This may all seem a lot more complicated, and I guess it is, but it doesn't involve changing your IT. The choice is yours, really.

Another thought would be to use ImpRec to do all the hard work for you. If you don't have this tool, get it. It's essential for just about any unpacking job. The idea goes something like: Fire up your target and patch the address of Sleep into the null entry following the kernel32 thunk. Now use ImpRec to rip a copy of the IAT and cut the thunk after your new entry. Now 'Fix Dump' on your target. This will add an extra IT to the end of your file, which you said you didn't want, but you should be able to work around this by telling ImpRec to generate new imports by ordinal (hence making the IT smaller than the existing one) and then planting the new IT directly over the old one.

Maybe I should stop typing now. I'm sorry if this is too much for you, but better too much than too little, right?

Keep us posted on your progress
Admiral

N8di8
April 27th, 2006, 15:49
1.
How did you convert 18974A00 into 004A9718 (not: 004A9781) or is it just a typo?

2.
My uncompressed test target contains the following reference (taken from OllyDbg):

004049FC $-FF25 38424100 JMP DWORD PTR DS:[<&kernel32.Sleep>] ; kernel32.Sleep

If I convert 38424100 into 00142483 (?) and "goto" 00142483 I see:

00142483 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00142493 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
001424A3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
001424B3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
001424C3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
001424D3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
001424E3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
001424F3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00142503 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00142513 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00142523 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00142533 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00142543 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00142553 00 AB AB AB AB AB AB AB AB EE FE EE FE 00 00 00 .««««««««îþîþ...
00142563 00 00 00 00 00 66 00 66 00 5F 07 1C 00 00 00 00 .....f.f._....
00142573 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00142583 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00142593 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
001425A3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

3.
If I open the UPX-compressed, patched target with OllyDbg I can't find any reference to sleep (except my "own" call):

0041AA80 > $ 68 00500000 PUSH 5000 ; /Timeout = 20480. ms
0041AA85 . E8 B8793E7C CALL kernel32.Sleep ; \Sleep
0041AA8A .^E9 81FEFFFF JMP UPXtarget.0041A910

Moreover, if I click with the mouse ony my sleep call, OllyDbg tells me that: 7C802442=kernel32.Sleep

If I open the UPX-compressed, patched target with PE Editor and look at the imports, I can't see any reference to sleep (under kernel32.dll).

4.
The UPX-compressed, patched target runs perfectly under XP SP2 but crashes under XP SP1.

5.
After I added the sleep import with the help of PE Editor to the UPX-compressed, patched target I can find the following:

0041C0BD 00 00 00 00 00 00 00 00 00 00 00 4B 65 72 6E 65 ...........Kerne
0041C0CD 6C 33 32 2E 64 6C 6C 00 00 00 53 6C 65 65 70 00 l32.dll...Sleep.
0041C0DD >42 24 80 7C 00 00 00 00 00 00 00 00 00 00 00 00 B$€|............

6.
Yipee..got it. Now I did:

0041AA80 > $ 68 00500000 PUSH 5000 ; /Timeout = 20480. ms
0041AA85 FF15 DDC04100 CALL DWORD PTR DS:[<&Kernel32.Sleep>] ; kernel32.Sleep
0041AA8B ^E9 80FEFFFF JMP UPXtarget.0041A910



This also works on SP1.

7.
Now I need to initialize and release winsock. But first I need some sleep...

Kayaker
April 27th, 2006, 20:20
Quote:
[Originally Posted by N8di8]1.How did you convert 18974A00 into 004A9718 (not: 004A9781) or is it just a typo?


Nope, take another look at Admiral's explanation

You can extract the numerical address from the opcode. FF15 is 'CALL DWORD PTR', and 18974A00 is the little-endian DWORD for the IAT pointer. Split this into bytes and reverse the order to get 004A9718 (i.e. convert to big-endian)

Quote:
2.If I convert 38424100 into 00142483 (?) and "goto" 00142483 I see:


As above, the address should be 00 41 42 38
The "big-endianess" is flipped as groupings of 2 hex character units, not 1

Quote:
4.The UPX-compressed, patched target runs perfectly under XP SP2 but crashes under XP SP1.


You must be using a hardcoded import address, you can't do that if you want it to run on all versions. This is an involved explanation I don't have time for right now..

Quote:
7.But first I need some sleep...


Yep, get some sleep

Kayaker

N8di8
April 27th, 2006, 23:56
1.
"If I convert ...": Thanks @ Kayaker. Now I got it. I was flipping a little bit too much ;-)

2.
Uncompressed targt -- If I "goto" 00 41 42 38 it looks much better:

00414238 >42 24 80 7C 79 E0 81 7C C4 2F 88 7C 3B 29 82 7C B$€|yà�|Ä/ˆ|‚|
00414248 >51 28 81 7C 63 4C 81 7C 28 AC 80 7C 29 B5 80 7C Q(�|cL�|(¬€|)µ€|

42 24 80 7C looks familiar ;-)

N8di8
April 29th, 2006, 02:46
Thanks everybody and in particular Admiral for his detailed explanations. Due to your help I had no problems whatsoever to initialize and release winsock. Consequently, my mini-project has been successfully completed.

Now I need to look for another job ;-)