Well, let's not forget that there are also young future crackers
reading these pages... "Hey? How comes that there is a compare and no
conditional jump there?"
So I thought that the following small
+HCU training exercise
could have some interest for future +HCUkers... have a look once more at
the following three lines from PNA's target code, I'll comment them a little:
:4EB04176 83F801 cmp eax, 1 ;this cmp sets the carry flag ON (if 0) or OFF (if not 0)
:4EB04179 1BC0 sbb eax, eax ;if ax<>0 -> ax=0 if ax=0->ax=FFFF
:4EB0417B 40 inc eax ;ax=0 only if 0 at the beginning
;else ax=1, whatever it was
See, sbb is "integer subtract with borrow", the contrary of adc
(add with carry).
If the carry flag is set,
the result of the instruction sbb ax,ax
changes and is equivalent to dec ax (a decrement of one).
Here the instruction cmp eax,1 sets the carry flag (CY) if ax was
zero, and it will be NC (Non Carry) if ax was anything else but zero.
What does this mean? It means that after these three instructions
you'll have in ax either zero or one,
zero if ax was zero and one if ax was not zero,
indipendently of the starting value of ax. So now we'll return either
with zero and carry set or with 1 and carry not set.
Here are some other interesting examples... see
if you understand these snippets (best answers will be premied with nice
strategic gamez):
From Ecstatica2... a nice game I'm cracking right now
(sbb and or)
:A9D68 38EC cmp ah, ch
:A9D6A 19C0 sbb eax, eax
:A9D6C 0C01 or al, 01
:A9D70 C3 ret
(sbb, inc and je)
:B53F4 668B38 mov di, word ptr [eax]
:B53F7 668B7002 mov si, word ptr [eax+02]
:B53FB B405 mov ah, 05
:B53FD B003 mov al, 03
:B53FF CD31 int 31 ;Ah! By the way... Int31 05/03 :-)
:B5401 19C0 sbb eax, eax
:B5403 40 inc eax
:B5404 7410 je 000B5416
From Textpad32... an interesting application that has already been cracked black and blue
(a simple "neg" variation)
:401EAA 83F801 cmp eax, 00000001
:401EAD 1BC0 sbb eax, eax
:401EAF F7D8 neg eax
(Hey: what's going on here?)
:40380F 8945EC mov [ebp-14], eax
:403812 837DDC01 cmp [ebp-24], 00000001
:403816 1BC0 sbb eax, eax
:403818 F7D8 neg eax
:40381A 8945DC mov [ebp-24], eax
:40381D 8B45EC mov eax, [ebp-14]
(Somebody else is compared...)
:405BC5 837DD401 cmp [ebp-2C], 00000001
:405BC9 1BC0 sbb eax, eax
:405BCB F7D8 neg eax
(The last two snippets for today's exercise :-)
:4086CB FF30 push dword ptr [eax]
:4086CD 83FA01 cmp edx, 00000001
:4086D0 1BC0 sbb eax, eax
:4086D2 24FD and al, FD
:4086D4 0529010000 add eax, 00000129
:4086D9 50 push eax
:415CD0 83F801 cmp eax, 00000001
:415CD3 1BC0 sbb eax, eax
:415CD5 24FC and al, FC
:415CD7 83C009 add eax, 00000009
:415CDA 50 push eax
Well... explain the above snippets, just looking at the code, you don't need to dig out the
relevant programs... use symdeb if you really don't
understand, for instance:
a 100/nop/nop/nop/cmp ax,1/sbb ax,ax/inc ax/nop/nop/nop/enter
And now that you have assembled your example, test it:
u 100/t=100/t/rf/CY/t/rax=1/t/
t=100/rax=FFAA/t/ and so on... flags changing through rf CY or rf NC,
new register values
in ax for testing through
rax=whatever :-)
This will teach you how much FUN you can have testing assembly code, and, moreover,
you'll begin to understand that EACH compiler uses slightly different
constructions, and
that the reverse engineering of the sbb instruction "sequences"
can be also used pretty effectively in order to understand which
compiler has been used by the programmers of your target...