flat assembler
Message board for the users of flat assembler.

Index > Windows > Question about locals (stack variables)

Author
Thread Post new topic Reply to topic
StakFallT



Joined: 19 Jan 2006
Posts: 50
StakFallT 19 Nov 2017, 19:03
Is it possible to pass a local variable (variable taking up space on the stack) to another procedure? Obviously, when moving to another procedure causes a new stack frame to be created and the esp/ebp registers no longer will match what they were before. However, let's say I had:

Code:
proc some_procedure_A SomeParameter:DWORD, SomeOtherParameter:DWORD
locals
     Str_Escaped: dd 0
endl
    


and I want to pass Str_Escaped to a string that actually generated an escaped string. Obviously the variable being on the stack is not going to have a heap address, and the complexities of the stack frames being different once control-flow is passed to another function , would it be possible to take the absolute address of the variable sitting on the stack and pass that to another function?

Right now I have something along the lines of:
Code:
proc some_procedure_A UnEsc_String:DWORD, SomeOtherParameter:DWORD
locals
     Str_Escaped: dd 0
endl


     ...


     push edx
     xor edx, edx

     lea edx, [Str_Escaped]

         push EscapeCharacter
         push edx
         push UnEsc_String
     call Escape_String 
    


I'd like to have the Escape_String procedure operate on the stack location that Str_Escaped (now stored in edx) is sitting at. However, it doesn't seem to work correctly. It's not failing, but it's value is never changed. It's changed in the "current" stack frame of the new procedure, but not of the calling procedure. I could always set eax to the value and return that and then set it in the calling procedure, but I'd like the procedure to be able to operate on a passed in local if possible.

Is this not working (or maybe not possible) because the address is based on a "relative" position and upon entering another procedure the relative position is no longer correct? Thanks!

-- StakFallT
Post 19 Nov 2017, 19:03
View user's profile Send private message Reply with quote
Furs



Joined: 04 Mar 2016
Posts: 2493
Furs 19 Nov 2017, 20:38
You can certainly take the address of a local variable; after all, [esp+X] resolves to an absolute address, so when you use it in lea, you get an "absolute" address, even though 'X' is relative to esp. This is very common actually, but only if the called function is down the stack chain.

Note that you can't use that address to a function "above" yours (i.e. your function returns to it) because then the address points below 'esp' which is considered invalid and can be trashed by any other calls etc.

The stack is not super special. It's just a memory region, like the heap, and esp is just a normal pointer to it. It has a few "special" quirks (mostly due to the OS, not the processor) but you don't need to worry about that right now (it's low level stuff with exceptions).

Everytime you call or push something on the stack, the pointer gets decremented. Any address above the pointer is valid to pass around other functions, so as long as esp is below your "address" that you pass to another function, it's perfectly fine and common.

I don't know why it's not working, but your code looks valid to me, I suspect Escape_String is wrong itself. Did you take the value from the stack and then dereference it? Showing Escape_String will solve the problem.


BTW the xor edx, edx is redundant Wink
Post 19 Nov 2017, 20:38
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20300
Location: In your JS exploiting you and your system
revolution 20 Nov 2017, 00:10
Str_Escaped is only four bytes in length, three bytes for characters and one byte for the terminating zero. Are you sure it isn't a pointer to a string? If it is then you push the value of the pointer, not the address of the pointer.
Code:
;...
         push EscapeCharacter
         push dword[Str_Escaped] ;<--- push the value?
         push UnEsc_Strin
;...    
BTW: If you remove the colon then you can remove the size override.
Code:
     Str_Escaped dd 0 ;no colon
;...
         push [Str_Escaped] ;no "dword" override needed
;...    
Post 20 Nov 2017, 00:10
View user's profile Send private message Visit poster's website Reply with quote
StakFallT



Joined: 19 Jan 2006
Posts: 50
StakFallT 20 Nov 2017, 02:25
@Furs ok I think I got it working. It seems I had to lea the variable to a register and pass that, and then inside the procedure I had to lea the parameter again (for when I pass it to my memory allocation procedure). It's kinda screwy but I think it makes sense now. I needed the first lea for the stack address (didn't want to use hardset/static relative-addresses) but then when they gets passed to another procedure, that value gets put into a "temporary" that is... on the stack. thus, I then had to lea that parameter since being in the new procedure is another stack frame all of its own (which I know... it just didn't dawn on me). Either way, I'm going to have to abandon using the local variables though I think (or at least accessing them directly) because it seems when I come back from that second routine, esp's address goes higher pushing the modified parameter quite a bit lower since that second procedure does a bunch of other stuff as well. I could allocate something on the heap and pass that around, I could use globals, etc. There's some options but I think I'm definitely going to have to think this through. Thanks!



@revolution since my original post, I have modified the code. It now looks like

locals
Str_Escaped rd 4
endl

You did say something rather interesting... I thought addresses even as values are still stored as 4 bytes, because the registers are 4 hexadecimal values (on 32-bits) and memory addresses are natively DWORDs (on 32-bits)? I'm pretty sure I've seen addresses butted right up next to each other with no null-terminator in between. Is that incorrect? Should there still be null-terminators. I feel like, obviously, strings needs null-terminators, but memory addresses it's assumed to be 4-bytes, though I guess depending on how they're being read (is a variable already set to its value and you're passing that around vs. actual string parsing of that memory address) it could matter.
Post 20 Nov 2017, 02:25
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20300
Location: In your JS exploiting you and your system
revolution 20 Nov 2017, 02:36
If you are storing string data at the address Str_Escaped then it might be more prudent to define it as byte data
Code:
Str_Escaped rb 16 ;16 bytes of data    
When you use "rd 4" you still reserve 16 bytes (4 dwords) but the label is tagged as dword data. This "works" if you only ever use LEA to get the address but it makes the code harder to understand.

For 32-bit code addresses are indeed 4 bytes, you don't need any terminator bytes between them. But don't confuse the address with the value at the address. You can use a 32-bit register to point to the address of a single byte
Code:
var db 0x12
mov esi,var ;<--- esi is a 32-bit address pointer to the single byte 0x12
mov al,[esi] ;<--- al now has the value 0x12    
Post 20 Nov 2017, 02:36
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.