flat assembler
Message board for the users of flat assembler.

Index > Main > local pointer passed to function as parameter.

Author
Thread Post new topic Reply to topic
khanh1984



Joined: 13 Jul 2009
Posts: 17
khanh1984 24 Jul 2009, 07:45
Hi Everybody ,

today I'm experimenting with using pointer inside assembler. So passing the global variable as a pointer to a function should be easy job for everybody but how about passing the local pointer.

Basically, if you use macro facility coming with Fasm package then local variable is translated to EBP-value (value is multiple of 4),passing the memory value is done with bracket[ ]. but passing a local pointer is different, because the function will use this offset referenced to DS segment while the memory value uses SS (stack segment). After several trial to work around and come up with simplest solution, I use the instruction LEA eax,[EBP-value]. Hence eax = ebp-value. The program works great but it works because SS and DS have same value (I verify this by using OllyDBG). So my question is:

1. In Windows, Do SS and DS segment always equal.
2. If we can't gurantee these two segments are the same and what is the simplest method to achieve my object above. I come to several solutions but it seems not optimal, eg:
Code:
lea eax,[EBP-value]
popDS
pop SS
push DS
call function,eax....
push DS (restore DS)
    


However the code above is not clean, if the function uses the global variable then DS value would point to incorrect position.

Anyone has a better solution?
Post 24 Jul 2009, 07:45
View user's profile Send private message Reply with quote
bitshifter



Joined: 04 Dec 2007
Posts: 796
Location: Massachusetts, USA
bitshifter 24 Jul 2009, 09:31
call function,addr [ptr]
Post 24 Jul 2009, 09:31
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 24 Jul 2009, 10:07
but instead of call, you have to use some macro, like stdcall, ccall, or invoke
Post 24 Jul 2009, 10:07
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Pirata Derek



Joined: 31 Oct 2008
Posts: 259
Location: Italy
Pirata Derek 24 Jul 2009, 10:30
The DS segment is always 23h in user-mode because the NT Kernel set it always on this value when returning from kernel-mode and DS isn't changed directly every SYSTEM CALL.
Also SS is always 23h in user-mode but every PRIVILEGE-LEVEL CHANGE it changes value (for example SYSENTER set SS always to 10h)

If your program changes DS and you need it in the corret value to point your local var, simply store old DS value and set DS = 23h
Code:
; Temporary DS change

push DS ; old DS value into stack
pushw 23h ; new DS value into stack
pop DS ; new DS value
...
... ; Do what you want
...
pop DS ; set DS to old value    

Rarely user-mode PE programs change segments because they may go in a General Protection Fault and then be killed by system.
Programmers should keep out from GP fault.

I think you don't need change DS because 23h segment starts from 0 linear address to 4 GB (has granularity), with RPL = 3 and read/write permissions.
Then don't care to DS or SS when programming.
Point to local vars as classic way.
Post 24 Jul 2009, 10:30
View user's profile Send private message Send e-mail Reply with quote
khanh1984



Joined: 13 Jul 2009
Posts: 17
khanh1984 24 Jul 2009, 16:51
To VID and bitshifter:
an example like this:

Code:
proc function
local xyz structure ;the structure
...
invoke API_function,xyz (want to pass xyz as pointer instead of [xyz]
endp
    

fasm will translate the invoke call as
push ebp-value (ebp-value is xyz)
call [API_function]

of course, as you see the push is illegal so the above code won't work
then we have big problem with local pointer (xyz) passing to the function (the problem is different from global when the above code works perfectly)

Then if what Pitara said is true, DS and SS is always pointing to same address, we simply use ebp-value for that pointer.

To Pirata:
could you point me to your reference source which mentions your above comment ? your help will be a great value to me.

And your solution you propose on changing DS, I think it is the same technique I mention in very 1st post, however as I said the function call (not the function containing the local ponter but the function we call inside) don't know that DS has been changed, if that function has another global pointer which definitely reference to DS segment then your posted solution will fail, since now that function has both pointers, one reference to SS segment, other reference to DS segment. I wonder in the HLL such as C or Delphi, do they care all about this (as I see the program in C use both local pointer and global pointer as passed parameters). or they are completely sure that SS and DS pointing to the same address, then my consideration is trivial one.
Post 24 Jul 2009, 16:51
View user's profile Send private message Reply with quote
Fanael



Joined: 03 Jul 2009
Posts: 168
Fanael 24 Jul 2009, 20:42
Maybe:
Code:
lea eax, [xyz]
invoke some_func, eax    
Post 24 Jul 2009, 20:42
View user's profile Send private message Reply with quote
khanh1984



Joined: 13 Jul 2009
Posts: 17
khanh1984 25 Jul 2009, 01:56
To Faneal, your code is the same in my first post.

so I'll forget about DS and SS segment like Pirata's advice, Things would be much simpler
Post 25 Jul 2009, 01:56
View user's profile Send private message Reply with quote
khanh1984



Joined: 13 Jul 2009
Posts: 17
khanh1984 25 Jul 2009, 07:23
someone knows how to implement the macro to do the lea instruction automatically. I've thought about something look like:

Code:
macro pushd arg
{
done@push equ
match ebp+value,arg
\{
lea ebx,arg
push ebx
restore done@push
\}
match  ,done@push
\{
push arg
\}
}
    


but my code won't work ?? maybe someone can point me where the error is.
Post 25 Jul 2009, 07:23
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8357
Location: Kraków, Poland
Tomasz Grysztar 25 Jul 2009, 08:15
The argument to macro may just be a label - and no matter if label is absolute value, or register-based, for assembler it's the same kind of entity. Thus to be able to determine what kind of label it is, you have to this kind of trick:
Code:
macro pushd arg
{
 if arg eqtype eax ; first eliminate the case of single register argument
  pushd arg
 else if [arg] eqtype [0] ; process only if argument forms a valid address
  local ..instruction,modrm
  virtual
   ..instruction: lea eax,[arg]
   load modrm byte from ..instruction+1
  end virtual
  if modrm = 5
   push arg
  else
   lea edx,[arg]
   push edx
  end if
 else
  pushd arg
 end if
}    
Post 25 Jul 2009, 08:15
View user's profile Send private message Visit poster's website Reply with quote
Pirata Derek



Joined: 31 Oct 2008
Posts: 259
Location: Italy
Pirata Derek 25 Jul 2009, 13:32
OK, Khanh1984.

Can you list me what i have to point you?

1) How kernel set DS and SS when returning to user-mode?
2) How descriptor pointed by 23h segment is made?
3) A program that check if DS changes after a system call?
4) A program that dimostrate that pointing with DS or SS is the same?

tell me
Post 25 Jul 2009, 13:32
View user's profile Send private message Send e-mail Reply with quote
khanh1984



Joined: 13 Jul 2009
Posts: 17
khanh1984 27 Jul 2009, 01:23
To Tomasz:

in the proc32.inc
Code:

macro local [var]
 { common
    locals
   forward done@local equ
    match varname[count]:vartype, var
    \{ match =BYTE, vartype \\{ varname rb count
                           restore done@local \\}
       match =WORD, vartype \\{ varname rw count
                            restore done@local \\}
       match =DWORD, vartype \\{ varname rd count
                            restore done@local \\}
       match =PWORD, vartype \\{ varname rp count
                           restore done@local \\}
       match =QWORD, vartype \\{ varname rq count
                           restore done@local \\}
       match =TBYTE, vartype \\{ varname rt count
                           restore done@local \\}
       match =DQWORD, vartype \\{ label varname dqword
                               rq count+count
                              restore done@local \\}
       match , done@local \\{ virtual
                            varname vartype
                            end virtual
                         rb count*sizeof.\#vartype
                          restore done@local \\} \}
    match :varname:vartype, done@local:var
    \{ match =BYTE, vartype \\{ varname db ?
                         restore done@local \\}
       match =WORD, vartype \\{ varname dw ?
                                restore done@local \\}
       match =DWORD, vartype \\{ varname dd ?
                                restore done@local \\}
       match =PWORD, vartype \\{ varname dp ?
                               restore done@local \\}
       match =QWORD, vartype \\{ varname dq ?
                               restore done@local \\}
       match =TBYTE, vartype \\{ varname dt ?
                               restore done@local \\}
       match =DQWORD, vartype \\{ label varname dqword
                               dq ?,?
                              restore done@local \\}
       match , done@local \\{ varname vartype
                           restore done@local \\} \}
    match ,done@local
    \{ var
       restore done@local \}
   common
    endl }
    

the macro argument has been broken to many pieces, (var broken into structure like "varname[count]:vartype", so I assume this argument isn't an entity at all and can be broken. (I must misunderstand some points in your manual )
Also in the line "match :varname:vartype,done@local:var
done@local equ whitespace, so why don't you just use
match varname:vartype,var since it is much shorter and simpler.
When I look at the buches of macro just you implement, I totally get lost.
Another question is regarding to eqtype. the type in the document you mention was only interger (such as arg eqtype 5), float (arg eqtype 1.0), string (arg eqtype "") but now I know it also can be address (arg eqtype [5]), register (arg eqtype eax, can I use ebx,ecx instead ?)... I mean what else of the type it could be, e.g segment register DS,ES, stack register SS ????

Another question, to the macro I mention above, as you can broken macro argument into many part why I can't broke it into ebp+value or even register+value then do the match condition register = ebx,value eqtype integer.... ???


to Pirata Derek,
I imagine that you know so well how Windows system operates deeply inside so I just ask for that reference, not specific points (as I know nothing Smile))
Post 27 Jul 2009, 01:23
View user's profile Send private message Reply with quote
khanh1984



Joined: 13 Jul 2009
Posts: 17
khanh1984 27 Jul 2009, 03:24
My question above is reduntdent The label is an entity, i did confuse with argument.
Post 27 Jul 2009, 03:24
View user's profile Send private message Reply with quote
Pirata Derek



Joined: 31 Oct 2008
Posts: 259
Location: Italy
Pirata Derek 27 Jul 2009, 08:33
How NT Kernel set DS after executing requested native API
Used IDA pro disassembler

This is where sysenter go in NT Kernel.
The rectangle where is the grey selection is for SYSENTER, the rectangle where is the yellow one is for INT 2Eh.
(Check how kernel starts to set DS and ES below both mov ecx,23h)

Image

After executing the requested Native API using KeServiceDescriptorTable, NT kernel set some important register like they were before Native Api Execution.
(Not all registers are set, only the most importants) The left is for INT 2eh, the right is for SYSENTER

Image

Here DS get its value from the "INFINITE" kernel stack values....
I need about 13 images to see you the complete operation.
(You can lost yourself if you follow all the CALLs Shocked )

Image

If you want to see all the procedure you have to Disasseble the NTOSKRNL.EXE
(this image is too big to see in a monitor!)
If you want the IDB file for IDA, (so you can analyze all this) tell me... Cool
Post 27 Jul 2009, 08:33
View user's profile Send private message Send e-mail 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.