0

I am currently working on a old 90's video game to try to correct/modify unrealistic behaviors.

I managed to almost complete my list, but it remains my main objective...

It is a management game, and if you are a poor manager, your boss simply fire you, sometimes for debatable reasons. I found where the "You are fired" pannel is launched, but I have some difficulties to understand the mecanism. Could someone help me to understand the below code?

Note that according to IDA it is a 16 bits application.

    mov     eax, dword_5F94E0  // copy the content of dword in eax
    mov     ecx, eax // copy eax in ecx
    lea     edx, [eax+eax*4] // ??
    lea     eax, [edx+edx*8] // ??
    shl     eax, 8 // ??
    add     eax, ecx // add ecx to eax
    lea     edx, [eax+eax*2] // ??
    mov     eax, dword_9FB922[ecx+edx*2] // ??
    lea     ecx, dword_9ECB20[ecx+edx*2] // ??
    sub     eax, 2C5h // remove 709 from eax
    cmp     eax, 0Dh // compare eax to 13
    ja      short loc_42D480 // jump if eax > 13 (not fired) else fired

I know there is the easy way to change the behavior of the last line.But it seems it is more complicated: doing so only prevent the "You are fired" panel to be displayed, but you are still sacked.

  • "Note that it seems it is a 16 bits application." and uses 32-bit registers? – Paweł Łukasik Feb 12 '17 at 13:40
  • Yes. I said "it seems" because IDA Pro said that. On the other hand, when I looked at the assembly documentation, I saw it refers to 32 bits registers. I don't have the skills to understand. May be it simply comes from IDA. – enrico69 Feb 12 '17 at 14:16
  • instructions like "lea edx, [eax+eax*4" are often used to do multiplications: edx := eax * 5 – Willem Hengeveld Feb 12 '17 at 20:29
  • if i calculate it correctly, the "mov eax, dword_9FB922[ecx+edx*2]" becomes: eax := dword_9FB922[69127 * dword_5F94E0] ... which as aGGeRReS remarks, a bit odd, since there is no factor of '4' in the index. – Willem Hengeveld Feb 12 '17 at 20:35
2

Without taking into account 16/32bit problem you already mentioned I'll try to explain what the code does (if this is what you exactly asked for):

mov eax, dword_5F94E0 // copy the content of dword in eax

mov ecx, eax // copy eax in ecx

lea edx, [eax+eax*4] // LEA stand for "load effective address", so after this line EDX will contain and ADDRESS of memory cell with address of eax+eax*4

lea eax, [edx+edx*8] // Similar to previous line. For me - looks a bit stupid, to calculate next address out of the previous one. For me this is an indicator of some problems during disassembly/debugging, but I am not very experienced to claim it to be true for 100%.

shl eax, 8 // SHL stands for Shift Left. It shifts the content of EAX bitwise on 8 bits, which is equal to multiplying it by 256. If some non-zero bits were shifted "out of" register - CF flag will be raised.

add eax, ecx // add ecx to eax

lea edx, [eax+eax*2] // Similar to previous LEA commands.

mov eax, dword_9FB922[ecx+edx*2] // dword_9FB922 seems to be a DWORD array or matrix. So base-index addressing is used. ecx+edx*2 refers to a particular element of an array (or matrix, look here for an explanation Link). The strange thing here is that usually, when working with DWORD (4-byte-element array) you have to multiply (scale) by 4 and not 2. This might be just a wrong naming from IDA.

lea ecx, dword_9ECB20[ecx+edx*2] // Same thing here.

sub eax, 2C5h // remove (subtract) 709 from eax

cmp eax, 0Dh // compare eax to 13

ja short loc_42D480 // jump if eax > 13 (not fired) else fired.

I recommend to review the data in all that dword_* variables. Hope this helped you.

1
mov     eax, dword_5F94E0  // copy the content of dword in eax
mov     ecx, eax // copy eax in ecx
lea     edx, [eax+eax*4] // ??

edx=eax*5

lea     eax, [edx+edx*8] // ??

eax=edx*9, i.e. the dword_5F94E0*5*9

shl     eax, 8 // ??

eax=eax*256, i.e. the dword_5F94E0*5*9*256

add     eax, ecx // add ecx to eax

eax=new eax+dword_5F94E0, i.e. the dword_5F94E0*5*9*256+dword_5F94E0

i.e. dword_5F94E0*11521

lea     edx, [eax+eax*2] // ??

edx=eax*3, i.e. dword_5F94E0*11521*3

mov     eax, dword_9FB922[ecx+edx*2] // ??

eax=value from array[dword_5F94E0+dword_5F94E0*11521*3*2]

i.e. eax=value from array[dword_5F94E0*69127]

lea     ecx, dword_9ECB20[ecx+edx*2] // ??

irrelevant for this purpose

sub     eax, 2C5h // remove 709 from eax
cmp     eax, 0Dh // compare eax to 13
ja      short loc_42D480 // jump if eax > 13 (not fired) else fired

So that's a really large array that is being queried to fetch a small value.

However, the most interesting part would be to look in that array to see which indices match the value of 0x2C5+0x0D, since they trigger the "fired" code path.

Given those, you can work out what value in dword_5F94E0 would access each of those indices, by dividing the index by 69127.

From there, you can search the rest of the code for writes to dword_5F94E0 with those values. Then you will have the events that are interesting.

At that point, you can presumably change the event value to something that won't trigger the "fired" code path.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.