The task is to add the code to the working state.

some_var dd ? ... // код // здесь мы имеем в регистре eax, к примеру, адрес переменной some_var 

The solution is obvious - lea eax, [some_var] , but it does not suit me for the reason that it is not position-independent (I tried to translate it into Russian in the title of the question). In other words, I need a code that can be copied together with the data at any address and get it in working order. Variables must have been global.

My decision is based on the fact that the difference between tag addresses does not depend on the position of the code. During compilation, you can find out the addresses of labels for a fixed address for placing a code, and its real position after the transfer - with the help of call $+5 , pop eax . Now I get out, but the resulting code is too cumbersome. On the other hand, it is not reflected in the source code, as it is wrapped in a macro.

The question is - is there a simpler solution? I use fasm, maybe its preprocessor is capable of that.


My version

  call $+5 label: lea eax, [label] sub [esp], eax lea eax, [var] add [esp], eax pop eax 
  • Add more code that you have in question. - insolor 4:08 pm
  • In my opinion, call $ + 5 is enough; pop eax; add eax, some_var - $ - 1. True, I can't check now. - insolor
  • I, unfortunately, also have no opportunity to check. I added my code from memory. - int3 pm

1 answer 1

I got about this code:

 format PE console include 'win32ax.inc' entry start section '.data' data readable writeable rb 7 ; Отступаем от начала секции на 7 байт, просто чтобы адрес переменной не был "ровным" some_var dd ? _fmt db '%p',13,10,0 section '.code' code readable executable start: mov eax, some_var cinvoke printf, _fmt, eax ; Эталонный адрес, в моем случае 00401007 call label1 ; Переход на следующую команду, в стек кладется адрес возврата, равный адресу label1 label1: pop eax ; Получаем адрес возврата из стека sub eax, label1 - some_var ; Уменьшаем адрес на разницу адресов переменной и метки label1 ; Разница label1 - some_var вычисляется в момент компиляции cinvoke printf, _fmt, eax ; Вычисленный адрес: 00401007 invoke ExitProcess, 0 section '.idata' import data readable library kernel, 'kernel32.dll', \ msvcrt,'msvcrt.dll' import kernel,\ ExitProcess, 'ExitProcess' import msvcrt,\ printf,'printf' section '.idata' import data readable library kernel, 'kernel32.dll', \ msvcrt,'msvcrt.dll' import kernel,\ ExitProcess, 'ExitProcess' import msvcrt,\ printf,'printf' 

In macro:

 macro get_addr var { local ..label1 call ..label1 ..label1: pop eax sub eax, ..label1 - var } 

local needed so that when you insert a macro each time new label names are generated. Two dots in front of the label name make the label global, but not becoming the parent label for local labels (starting from one point).

After calling the macro, the address of the variable will be in the eax register.

  • Thank. I did not know about the labels visible inside the macro (I had to do it through @@) and about the explicit subtraction of addresses, calculated at compile time. - int3
  • @ int3, you need at least once to skim through the manual on the fasm completely, even if not to understand everything (I didn’t comprehend the Zen macro), but at least to imagine what functionality the compiler provides. - insolor
  • gradually learn new, periodically leafing through manuals. By the way, the trick with .. did not work, I had to add a local label_name to the macro to hide it from the visibility outside the macro. - int3
  • @ int3, yes, that's right, you need to use local, now I’ll correct the answer. - insolor