Log in

View Full Version : How to assemble a loop? *pls don't beat me*


N8di8
April 29th, 2006, 21:20
I'm feeling so stupid...

1.
I understand the following code:

MOV AX, 5
DEC AX
...repeated instructions...
JNZ [address of DEC AX]

2.
Unfortunately, this simple loop does not work for me because register ax is used by the instructions that shall be repeated. Consequently, I want to use a memory address as a "safe place" for the counter.

3.
In principle, I would like to ...

MOV memoryaddress, 5
DEC memoryaddress
...repeated instructions ...
JNZ (with respect to memoryaddress)

4.
I have googled & googled ... but I mainly find high-level stuff which does not really help. Moreover, I read http://faydoc.tripod.com/cpu/jnz.htm according to which it should be possible to MOV bytes to a memory address. But somehow Ollydbg does not allow me to do something like "MOV 41b5ff, 5" because the syntax is wrong.

Please ... ;-)

naides
April 29th, 2006, 22:47
Quote:
[Originally Posted by N8di8]I'm feeling so stupid...

Consider yourself beaten

1.
I understand the following code:

MOV AX, 5
DEC AX
...repeated instructions...
JNZ [address of DEC AX]

2.
Unfortunately, this simple loop does not work for me because register ax is used by the instructions that shall be repeated. Consequently, I want to use a memory address as a "safe place" for the counter.

3.
In principle, I would like to ...

MOV memoryaddress, 5
DEC memoryaddress
...repeated instructions ...
JNZ (with respect to memoryaddress)


Do not use a Global absolute place in memory, like 41b5ff, which you have no idea who or what may overwrite. look for a different register that is not used, EDI or ESI may be wide open. you can check if they are zero with the isntrunction
test ESI, ESI
jnz [Begining of the loop]


or use a stack variable.

To use a stack, local variable you need to learn how local stack variables are created (by the instruction sub ESP, 04 ) and how they are referred to( using [EBP-04] )
See for instance: http://www.woodmann.com/forum/showthread.php?t=5849&highlight=good+mood+today

4.
I have googled & googled ... but I mainly find high-level stuff which does not really help. Moreover, I read http://faydoc.tripod.com/cpu/jnz.htm according to which it should be possible to MOV bytes to a memory address. But somehow Ollydbg does not allow me to do something like "MOV 41b5ff, 5" because the syntax is wrong.


If you insist on using MOV 41b5ff, 5 try square brackets:

MOV [41b5ff], 5. But in general using an absolute area in memory is a

Bad idea


Please ... ;-)


In blue.

N8di8
April 30th, 2006, 04:37
Thanks so much. EDI was indeed not used. Problem solved.

Admiral
April 30th, 2006, 10:41
One final note.

Although unlikely, your target may rely on that EDI at some later point. If you're at liberty to use up some more space (all two bytes), it would be good practice to preserve EDI with a PUSH/POP combination surrounding your loop.

Regards
Admiral

LLXX
April 30th, 2006, 21:41
If CX is unused...
Code:

mov cx, 5
Loopstart:
... your loop body ...
loop Loopstart
saves some bytes as well.

N8di8
May 1st, 2006, 02:32
@Admiral Thx. I will remember this.

@LLXX Am I right to assume that only Masm (but not OllyDbg or Hiew) understand this syntax?

naides
May 1st, 2006, 06:48
Quote:
[Originally Posted by N8di8]@LLXX Am I right to assume that only Masm (but not OllyDbg or Hiew) understand this syntax?



Nope. Loop is a native x86 assembly opcode, two bytes long. E2 ?? , where ?? is the 1 byte address offset of the begining of the loop. it automagically decreases CX with each loop. Both Olly and Hiew can assemble it.

It is not widely used by automatic compilers, perhaps it takes too many cpu ticks.

http://pdos.csail.mit.edu/6.828/2005/readings/i386/LOOP.htm

LLXX
May 2nd, 2006, 00:32
I remember this instruction quite vividly since I lost a size-coding competition by a single byte because of it - I used dec cx/jnz instead of loop.

I have never seen a compiler emit LOOP even when set to maximum size optimisation, most likely due to the ±127 bytes distance limitation. In the same way 16-bit compilers always do jnz/jmp pair even if the distance is less than 127 bytes. The compiler just doesn't have the intelligence to optimise at that level.

Admiral
May 2nd, 2006, 07:22
I think I remember Maximus telling me that LOOPD is runs slightly slower than DEC/JNZ. Seemed fairly convincing at the time. I'll provide no citation.

Regards
Admiral

Maximus
December 6th, 2006, 10:37
Well, i were reading this thread pointed by Woodmann for other reasons out of curiosity, so let me answer...

LOOP is usually microcoded, not hardwired, and thus it takes more time. I.e. on P4 family it is implemented with mmh... 5 mops if I remember well (depends on processor family, usually).
It was an excellent instructions up to x386 for speed purposes, then on x486 it has become slightly slower due to pipelining architecture, for becoming terribly slow in p1 and further processors.

Today it can only be used for exotic coding or some nice competition

(LOOPD can slow down a small cycle by at least 100% on P1, more on further Processors)

WaxfordSqueers
December 6th, 2006, 14:13
Quote:
[Originally Posted by naides;51354]Loop is a native x86 assembly opcode, two bytes long. E2 ?? , where ?? is the 1 byte address offset of the begining of the loop. it automagically decreases CX with each loop.
Could I use the LOOP instruction in softice to put it in an infinite loop while I break out of it to do something else? I know there is another code for that but I can never remember it while I'm in softice.

naides
December 6th, 2006, 14:55
Quote:
[Originally Posted by WaxfordSqueers;62893]Could I use the LOOP instruction in softice to put it in an infinite loop while I break out of it to do something else? I know there is another code for that but I can never remember it while I'm in softice.

It will automagically quit when CX hits 0, so you will need to finish what you wanted to do in a few miliseconds

Write Down: EB FE

TBone
December 6th, 2006, 15:37
Not as a single instruction. The LOOP opcode decrements the (E)CX register automatically. A LOOP opcode is functionally equivalent to doing this:
Code:
DEC ECX
JNZ NEAR xxxxxxx


So even if you do this:
Code:
0x04010000: LOOP 0x04010000

It will only loop until ECX=0

Something like this would loop infinitely, though:
Code:
Begin_loop:
INC ECX
LOOP Begin_loop


As far as I know, the simplest infinite loop is a JMP SHORT instruction that JMPs to itself, but perhaps I'm missing a neat trick.

Kayaker
December 6th, 2006, 15:50
Quote:
EB FE


I like
a eip
jmp eip

TBone
December 6th, 2006, 17:26
It took me a while to figure out what that meant. I'm guessing that "a eip" is the SoftICE command to assemble at EIP?
<--- SICE newb

Heh, that's interesting. I didn't know SICE would let you assemble that. Olly certainly doesn't. Taken literally, "JMP EIP" isn't a valid instruction; there's no ModR/M encoding for EIP. Apparently (from some tutorials I just googled up), SICE assembles that instruction as EB FE.

It would be nice if Olly added that, even if it is sort of wrong. The fastest way to do it in Olly right now is to use CTRL+E (binary edit) instead of using the assembler, although you can also tell Olly to assemble "DW 0FEEB". I kind of like that one - "FEEB" is easy to remember

Kayaker
December 6th, 2006, 18:46
Yeah that's right. Softice uses several internal routines which are based on the standard WinDbg WINDBG_EXTENSION_APIS define and which are available for external use through the same kernel debugger extension interface. One of these routines is the string parsing one PWINDBG_GET_EXPRESSION lpGetExpressionRoutine. Like the WinDbg version it recognizes and converts phrases like 'eip', 'eax' etc into their current values.
Actually the "a" command doesn't use the lpGetExpressionRoutine directly, it uses a slightly different routine, but the end result is the same.

WaxfordSqueers
December 6th, 2006, 19:07
Quote:
[Originally Posted by Kayaker;62898]I like a eip jmp eip
thanks Kayaker, I had forgotten that one. It seems the way I recall doing it was to write down the code for the eip instruction and EIP-1 for later replacement. Then you'd replace eip-1 with a NOP and the first two bytes of the EIP with EB FE, which of course, is jump -1. But there's something else I'm forgetting.

Your method seems a lot easier.

What do you do when you return from your side trip and want to carry on in softice? You should have written the code at the EIP down first, shouldn't you? If so, how would you insert it again without doing a manual memory edit?. Is that something like 'e eip xx yy', where xx and yy are the bytes overwritten by the 'a jmp eip'?

****I'm just correcting myself here, after readig TBone's reply. I guess the EB FE instruction is applied from the end of the instruction, meaning The FE sends it back one instruction to the EB again. The NOP at EIP-1 would not be correct, unless of course you wrote EB FD. :-)

WaxfordSqueers
December 6th, 2006, 19:23
Quote:
[Originally Posted by naides;62894]It will automagically quit when CX hits 0, so you will need to finish what you wanted to do in a few miliseconds Write Down: EB FE
thanks naides. I wasn't thinking. Forgot about the ecx.

blabberer
December 7th, 2006, 05:47
alt+f1
? eip
a eip,jmp "the result of ?eip shown in the dialog as hex"

or

alt+f1
l eip,waxfordsqueers
a eip, jmp waxfordsqueers

00401000 <waxfordsqueers> -EB FE JMP SHORT <OLLYDBG.waxfordsqueers> ; OLLYDBG.<ModuleEntryPoint>

or if you dont like commandline

press colon type a name of label
then hit spacebar or start typing to bring up the assembler dialog
type jmp label

Code:

00401000 <waxfordsqueers> -EB FE JMP SHORT <OLLYDBG.waxfordsqueers> ; OLLYDBG.<ModuleEntryPoint>
00401002 66 DB 66 ; CHAR 'f'
00401003 62 DB 62 ; CHAR 'b'
00401004 3A DB 3A ; CHAR ':'
00401005 43 DB 43 ; CHAR 'C'
00401006 <waxfordguiqueers> -EB FE JMP SHORT <OLLYDBG.waxfordguiqueers>




oh yeah ollydbg is as powerfull as sice or even more powerfull than sice
atleast in userland

im not saying it some supposed to be top class security researchers say that

http://www.matasano.com/log/620/hand-detouring-windows-function-calls-with-ht/

@kayaker
there is a link to a python interfaced hooking plugin for ollydbg in that link take a look and see if it is ok to be mirrored in stuph

Kayaker
December 7th, 2006, 10:49
Quote:
[Originally Posted by blabberer;62942]@kayaker
there is a link to a python interfaced hooking plugin for ollydbg in that link take a look and see if it is ok to be mirrored in stuph


I couldn't find it at the link (nice one btw), but I think you probably mean UHooker?
http://oss.coresecurity.com/projects/uhooker.htm

Yeah, I was going to Stuph it a while back, but I always like to test the plugins before including them there so I can make an informed description, never got the chance though. Actually, I just don't like to leech from what I see linked at OpenRCE. Will do it anyway, thanks for the heads up.

K.

blabberer
December 7th, 2006, 13:24
yep thats it its linked in the comments below in that link ouch i didnt notice its been there in openrce since 6 months thought it was some new avatar havent played with it myself yet

WaxfordSqueers
December 7th, 2006, 21:47
Quote:
[Originally Posted by blabberer;62942]
alt+f1
l eip,waxfordsqueers
a eip, jmp waxfordsqueers


thanks for the expose, Blabberer, and for putting me into posterity. I'm sure someone will come across this forum and wonder who the heck is waxfordsqueers.


Quote:
[Originally Posted by blabberer;62942]oh yeah ollydbg is as powerfull as sice or even more powerfull than sice atleast in userland
I have gone on record as having absolutely nothing against Olly. I intend to learn it; it's a matter of taking the plunge. By saying 'userland', I'm assuming you mean "ring 3" land. I'd like to hear more about the experience people have using it in Ring 0.

I've had good success recently tracing right into system functions like HAL from Ring 0...and back!! Moreover, I've been quite reckless about it, using the P <enter> combo to jump over functions in Ring 0. It seems something has been upgraded in softice recently because, in the past, doing that more often than not lead to a total crash or BSOD.

Kayaker
December 7th, 2006, 23:18
Quote:
[Originally Posted by WaxfordSqueers;62965]I've had good success recently tracing right into system functions like HAL from Ring 0...and back!! Moreover, I've been quite reckless about it


WONDERFUL!!!!
You have made me so happy

That's why I loved Sice so much. I would start to do a serial sniff (in the days when such a thing actually existed), and just keep right on tracing into ntoskrnl. Holy sh*t, LOOK at this thing, there's a whole Operating System under here, look at all these undocumented commands, so THIS is what an "API" actually is. Forget the serial sniff, this stuff is too cool.

Oh my that was a wonderful discovery. It's amazing how it put the whole 'userland' thing in perpective and absolutely opened my eyes to a whole new bank of knowledge just waiting to (try to) be understood. That's when reversing really caught my blood.

Truly, not to lessen usermode reversing at all, but you really can't see or appreciate the whole picture if you haven't at least experienced the ring3 -> ring0 -> ring3 transition and seen what is behind that 'closed' door.

It's like reading half a good book with the final chapters missing, or having sex with your clothes on, or kissing your sister, or... it's just's not the same!

Oh my, now you've got me all wound up

blabberer
December 8th, 2006, 03:50
Quote:
thanks for the expose, Blabberer, and for putting me into posterity


hehe that is termed as mnemonicking or some such jargon
i picked up that habit when i was trying to learn a little bit of russian

you know cow is spelt/pronounced as karova / korova
now imagine car over a cow holy carova == cow
that was a cute way to make one remember crap

also these catchwords normally turn up faster in searches if i ever need to quote something i dont have to remember much

also im sure you would always end up thinking jmp waxford jmp when ever you want to assemble an infinite loop ever

WaxfordSqueers
December 8th, 2006, 04:26
Quote:
[Originally Posted by Kayaker;62966]That's why I loved Sice so much. I would start to do a serial sniff (in the days when such a thing actually existed), and just keep right on tracing into ntoskrnl. Holy sh*t, LOOK at this thing, there's a whole Operating System under here, look at all these undocumented commands, so THIS is what an "API" actually is. Forget the serial sniff, this stuff is too cool.
I read some theory on it, most recently through the book by Russinovich, but it wasn't till I started exploring in there that I started to get the connection between HAL, NToskrnl, win32, ntdll, etc. I don't pretend to even remotely understand it but lights are starting to come on. It's amazing how many API functions are paralleled in there, then again, those are the real functions doing all the work, and much of what we see in userland are virtual.

Quote:
[Originally Posted by Kayaker;62966]Truly, not to lessen usermode reversing at all, but you really can't see or appreciate the whole picture if you haven't at least experienced the ring3 -> ring0 -> ring3 transition and seen what is behind that 'closed' door.
not only that, many of those functions are re-entrant, as I call it, probably incorrectly. You disappear into ring 0 and come out in another part of your app before returning to the calling code in the same app. If you didn't go down the rabbit hole, you'd miss that call back into your app and wonder what was happening.

Recently, for example, I had an app that was a GUI shell for a DOS-based app. I got to a point just before a Sleep function, where the DOS app was loaded by CreateProcess. The loading must have happened in the middle of CreateProcess, on a 'CALL K32!baseprocessstart. I haven't been able to spot where it happens, but that call in k32 sure is a dandy for a BPX.

Anyway, I've hijacked this guy's posting enough. See you back in Tools of the Trade. I need to post more about current softice happenings. First, I need to do the obligitory search through the archives to make sure my queries aren't glaringly obvious.

WaxfordSqueers
December 8th, 2006, 04:31
Quote:
[Originally Posted by blabberer;62973]hehe that is termed as mnemonicking or some such jargon i picked up that habit when i was trying to learn a little bit of russian
I tried to learn a bit of Russian when I was researching a crashed hard drive. I've heard that Russian isn't classified as a difficult language to learn, but for me, it was getting past the alphabet.

One of the techniques in memorization is to relate what you want to learn to something ridiculous rather than something common. Bet you'll never forget the car over the cow. I know I've never forgotten the image of the cow jumping over the moon.