Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


(continue of...) calling function doesn't work
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine
View previous topic :: View next topic  
Author Message
lawrenc3
Newbie cheater
Reputation: 0

Joined: 22 Mar 2020
Posts: 10

PostPosted: Fri Apr 02, 2021 8:26 pm    Post subject: (continue of...) calling function doesn't work Reply with quote

hi, this is a continue of
Code:
cheatengine.org/forum/viewtopic.php?p=5759220


I didn't have that much knowledge to continue the discussion, so I've studied a little bit more before treating these concepts.

so, what I'm trying to do is working with x64 assembly: I want to call a function from cheat engine tutorial program (x86_64 version).


ok, dark byte said that the passed arguments to the function "hit me" are rcx, rdx, r8, r9. that's the default x64 calling convention.

I've added a breakpoint on the call of the function that substracts health, and I'm looking at the registers.

(show the attached image)

why stacktrace doesn't show me the different rcx,rdx,r8,r9 registers values on "passed arguments"? are those pointers of something or what?
btw. I just wanted to know how I can directly see the passed arguments (the used registers) without having to manually check the code (if it was possible).

now, let's get to the point.

mov rcx,00000000016304A0
mov rdx,0000000001656300
mov r8,0000000000020A18
mov r9,0000000000020A18
call qword ptr [rax+000001F0]

would this call the function if I do a memory allocation (tell me how to allocate correctly a new memory portion) and create a thread on the first register assignment ("mov rcx,00000000016304A0")?

also how would 5 or 6 arguments get passed if default x64 convention uses just 4 registers?
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 150

Joined: 06 Jul 2014
Posts: 4657

PostPosted: Fri Apr 02, 2021 9:29 pm    Post subject: Reply with quote

lawrenc3 wrote:
the passed arguments to the function "hit me" are rcx, rdx, r8, r9.
If the function has 4 parameters, then yes. If it has less, some won't be used (e.g. only use rcx/rdx); if it has more, they'll go on the stack.

lawrenc3 wrote:
why stacktrace doesn't show me the different rcx,rdx,r8,r9 registers values on "passed arguments"?
I'd assume the values under "parameters" in the stacktrace are those that are stored on the stack. Practically, most functions don't have enough parameters to warrant using the stack, so this isn't that useful.

lawrenc3 wrote:
I just wanted to know how I can directly see the passed arguments (the used registers) without having to manually check the code (if it was possible).
To see the actual values of the registers, you need to set a breakpoint. If you only want to see which are being used by the function, you'd need more advanced code analysis than what CE offers to do that automatically.

lawrenc3 wrote:
would this call the function if I do a memory allocation (tell me how to allocate correctly a new memory portion) and create a thread on the first register assignment ("mov rcx,00000000016304A0")?
No. You're not assigning anything to rax, but you read from it in the indirect call. rax isn't going to magically be the thing you want it to be. The thread will also execute uninitialized memory after the call returns and will certainly crash (put ret after call, or better yet, use a tail call).

The values of registers might change between invocations (e.g. temporary objects created, used, and destroyed every time it's called). If they do, you won't be able to simply assign an immediate to the register(s).

allocating memory / creating a thread:
Code:
alloc(newmem,1024,Tutorial-x86_64.exe)
createthread(newmem)

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
lawrenc3
Newbie cheater
Reputation: 0

Joined: 22 Mar 2020
Posts: 10

PostPosted: Fri Apr 02, 2021 9:54 pm    Post subject: Reply with quote

ParkourPenguin wrote:
lawrenc3 wrote:
the passed arguments to the function "hit me" are rcx, rdx, r8, r9.
If the function has 4 parameters, then yes. If it has less, some won't be used (e.g. only use rcx/rdx); if it has more, they'll go on the stack.


"if it has more, they'll go on the stack" -> wrong assumption, afaik. Any parameters, independently from how many of them are passed, that the function is expecting are pushed onto the stack frame.

I don't think it's correct to say that r8 and r9 won't be used since it's the calling convention. they won't be used from the function that I'm calling, but they are still used from the caller.

ParkourPenguin wrote:
I'd assume the values under "parameters" in the stacktrace are those that are stored on the stack. Practically, most functions don't have enough parameters to warrant using the stack, so this isn't that useful.

I don't understand.

ParkourPenguin wrote:
To see the actual values of the registers, you need to set a breakpoint. If you only want to see which are being used by the function, you'd need more advanced code analysis than what CE offers to do that automatically.

ok.

ParkourPenguin wrote:
No. You're not assigning anything to rax, but you read from it in the indirect call. rax isn't going to magically be the thing you want it to be

you're correct. I didn't see that rax+1f0 within the call opcode.
so if I assign rax to the correct value, and put ret at the end will it work? please show me practically what you mean with "tail call".

ParkourPenguin wrote:
The values of registers might change between invocations (e.g. temporary objects created, used, and destroyed every time it's called). If they do, you won't be able to simply assign an immediate to the register(s).

I know, that's why I've let the function run twice to check if they changed (they didn't change).
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 150

Joined: 06 Jul 2014
Posts: 4657

PostPosted: Sat Apr 03, 2021 12:15 am    Post subject: Reply with quote

lawrenc3 wrote:
"if it has more, they'll go on the stack" -> wrong assumption, afaik. Any parameters, independently from how many of them are passed, that the function is expecting are pushed onto the stack frame.
Stack frames are located in the stack.
There is a shadow store for at least the 4 register parameters even if the function takes less; however, the caller can leave the shadow store uninitialized.
This stuff is documented here:
https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-160
Perhaps an example would help. This code:
Code:
int callee(int a, int b, int c, int d, int e, int f) {
    return a * (b + c) * (d - e) + f;
}

void caller() {
    callee(1, 2, 3, 4, 5, 6);
}
compiles to this:
Code:
a$ = 8
b$ = 16
c$ = 24
d$ = 32
e$ = 40
f$ = 48
int callee(int,int,int,int,int,int) PROC
  mov  DWORD PTR [rsp+32], r9d
  mov  DWORD PTR [rsp+24], r8d
  mov  DWORD PTR [rsp+16], edx
  mov  DWORD PTR [rsp+8], ecx
  mov  eax, DWORD PTR c$[rsp]
  mov  ecx, DWORD PTR b$[rsp]
  add  ecx, eax
  mov  eax, ecx
  mov  ecx, DWORD PTR a$[rsp]
  imul ecx, eax
  mov  eax, ecx
  mov  ecx, DWORD PTR e$[rsp]
  mov  edx, DWORD PTR d$[rsp]
  sub  edx, ecx
  mov  ecx, edx
  imul eax, ecx
  add  eax, DWORD PTR f$[rsp]
  ret  0
int callee(int,int,int,int,int,int) ENDP

void caller(void) PROC
  sub  rsp, 56
  mov  DWORD PTR [rsp+40], 6
  mov  DWORD PTR [rsp+32], 5
  mov  r9d, 4
  mov  r8d, 3
  mov  edx, 2
  mov  ecx, 1
  call int callee(int,int,int,int,int,int)
  add  rsp, 56
  ret  0
void caller(void) ENDP
x64 msvc 19.28 (VS 16.9); no optimizations
In callee(...), the first four instructions copy the register parameters into the shadow store for debugging purposes. In a release build, this would be foregone and they would be accessed through registers.
In caller(), notice how the first 4 parameters are passed through registers and the other 2 are passed through the stack after the 32-byte shadow store.

lawrenc3 wrote:
I don't think it's correct to say that r8 and r9 won't be used since it's the calling convention. they won't be used from the function that I'm calling, but they are still used from the caller.
I was talking about what the caller uses to pass arguments to the callee.

lawrenc3 wrote:
ParkourPenguin wrote:
I'd assume the values under "parameters" in the stacktrace are those that are stored on the stack. Practically, most functions don't have enough parameters to warrant using the stack, so this isn't that useful.

I don't understand.
CE has absolutely no idea how many parameters a function takes. It simply presents all the information it has regardless of the information's relevancy. Any values on the stack above the return address for the caller could be a parameter, so CE shows you the value. Maybe CE looks at the potentially uninitialized shadow store; I don't know.
Note that this information is for the current function, not for any function about to be called. It also assumes a stack frame has been established, so step over the first couple instructions that establish the stack frame when you step into a call.

lawrenc3 wrote:
so if I assign rax to the correct value, and put ret at the end will it work? please show me practically what you mean with "tail call".
I think it should, but I haven't seen your full script yet either.
Tail call:
https://en.wikipedia.org/wiki/Tail_call#In_assembly
In scripts where I create threads to run in memory the script allocates, I usually add a tail call to VirtualFree to deallocate memory safely. This post has a 32-bit .CT example, with an explanation of the code a few posts down:
https://www.cheatengine.org/forum/viewtopic.php?p=5657897
Here is a 64-bit equivalent of that tail call:
https://www.cheatengine.org/forum/viewtopic.php?p=5744208

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
lawrenc3
Newbie cheater
Reputation: 0

Joined: 22 Mar 2020
Posts: 10

PostPosted: Sat Apr 03, 2021 7:31 am    Post subject: Reply with quote

okok, with calm. we're both pretty confused on the argument.

ParkourPenguin wrote:
There is a shadow store for at least the 4 register parameters even if the function takes less


this is correct, from what I've read (in x64, the first 4 arguments passed to a function are not stored in the stack).

ParkourPenguin wrote:
lawrenc3 wrote:
so if I assign rax to the correct value, and put ret at the end will it work? please show me practically what you mean with "tail call".
I think it should, but I haven't seen your full script yet either.


from what you said on your last sentence I've quoted, this is not correct. or better, this is not coherent with what you wrote. I have to push these values on the "shadow space" (that's how msdn documentation names it), and (if there are any other) then the last arguments on the stack.

devblogs_microsoft_com/oldnewthing/20160623-00/?p=93735


(replace first two underscores with dots -- I can't post links yet since I'm a new member)

if you see how he pushes them (on the shadow space), he is getting the return address and he is pushing all of them (rcx, rdx, r8 and r9) 32 bytes above of it.

do you have any idea on how to redo this in my situation?

you can see the attached images, and know that's not working like we expected it to (it's crashing after creating a thread).
Back to top
View user's profile Send private message
Oxijen
Expert Cheater
Reputation: 0

Joined: 07 May 2020
Posts: 163
Location: On The Moon

PostPosted: Sat Apr 03, 2021 10:59 am    Post subject: Reply with quote

my fingers hurt after seeing all these typing O_O
_________________
I can see you Hitler
Especially When I am On the Moon!!
You are Right now in cheat engine forum Wink
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 150

Joined: 06 Jul 2014
Posts: 4657

PostPosted: Sat Apr 03, 2021 11:13 am    Post subject: Reply with quote

lawrenc3 wrote:
I have to push these values on the "shadow space" (that's how msdn documentation names it)
No, you don't need to push anything and you don't need to initialize it with any value.
msdn uses both "shadow space" and "shadow store" to refer to that 32 byte space on the stack.

If you use a regular call, then you'll have to create the shadow store yourself (I missed this):
Code:
sub rsp,28
mov ...
...
call ...
ret

If you use a tail call, then you don't, because you can simply reuse the shadow store the caller made for your code.
Code:
mov ...
...
jmp ...

lawrenc3 wrote:
https://devblogs.microsoft.com/oldnewthing/20160623-00/?p=93735
This isn't documentation. This is a guy's blog.
All the assembly code in there is showing what's bad about not preallocating that shadow store. It doesn't show what's actually going on under the current ABI.
In simple english, he is telling you what you shouldn't do.
Recursively read through the previous post linked in the first paragraph for a better idea of what's going on.
This post says the shadow store isn't anything special and the caller can use it for whatever purpose it chooses:
https://devblogs.microsoft.com/oldnewthing/20130830-00/?p=3363
This post actually goes into detail as to what the calling convention is and how to call functions:
https://devblogs.microsoft.com/oldnewthing/20040114-00/?p=41053

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
lawrenc3
Newbie cheater
Reputation: 0

Joined: 22 Mar 2020
Posts: 10

PostPosted: Sat Apr 03, 2021 11:52 am    Post subject: Reply with quote

ParkourPenguin wrote:
lawrenc3 wrote:
I have to push these values on the "shadow space" (that's how msdn documentation names it)
No, you don't need to push anything and you don't need to initialize it with any value.
msdn uses both "shadow space" and "shadow store" to refer to that 32 byte space on the stack.

If you use a regular call, then you'll have to create the shadow store yourself (I missed this):
Code:
sub rsp,28
mov ...
...
call ...
ret


that's exactly what I meant with "I have to push these values on the shadow space". I don't really understand why you are substracting from rsp (where did you define it?) if it's not defined anywhere. if you can help, could you complete the code basing on the screenshots I've posted? it's pretty hard to understand what you're trying to say practically (explain what you're doing, I would solve this problem faster), but I've abstractly understood what you meant.

ParkourPenguin wrote:
This isn't documentation. This is a guy's blog.

nobody said that's documentation. I've said that msdn mentions a "shadow space", while this blog made me understand (very approximately) how it's prepared while he specifies some bad approaches to this.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 150

Joined: 06 Jul 2014
Posts: 4657

PostPosted: Sat Apr 03, 2021 12:44 pm    Post subject: Reply with quote

rsp holds a pointer to the thread's stack. Subtracting from it "allocates" memory on the stack.

You should really learn the basics of x64 assembly before trying to write assembly yourself. Look up "x64 tutorial" or something.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
lawrenc3
Newbie cheater
Reputation: 0

Joined: 22 Mar 2020
Posts: 10

PostPosted: Sat Apr 03, 2021 2:39 pm    Post subject: Reply with quote

ParkourPenguin wrote:
rsp holds a pointer to the thread's stack. Subtracting from it "allocates" memory on the stack.

You should really learn the basics of x64 assembly before trying to write assembly yourself. Look up "x64 tutorial" or something.


I forgot that substracting/adding rsp is meant for allocating/deallocating stack. we both have gaps in the argument also if we studied x64 asm and that's reasonable (this is a pretty hard argument to treat today - we don't need to often use asm today and finding good references about these things may get to become hard), still I didn't tell you to learn the basics just because you missed to tell me to push the args on the shadow space. it just happens, we are humans.
sorry if I want to be frank (this is not meant to be rude), if you were able to help me I didn't need to get the words out of your mouth. you didn't tell me where to jmp, what to mov and other (that's what I'm asking you to do) but you are cutting off the code with dots (why?). I've asked you for a practical example (which I'll adapt to my final code): can you please show me what/how I should mov with a regular call after allocating rsp? and with the second method (with the one that you named "tail call") what/how should I mov and where should I jump?

elaborate on why I should prefer a tail call, don't name these things just to assume that everyone knows what you're thinking about.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 150

Joined: 06 Jul 2014
Posts: 4657

PostPosted: Sat Apr 03, 2021 4:11 pm    Post subject: Reply with quote

I'm not going to write the code for you, and while I will link to the information you want, I'm not going to copy and paste it here for you in a format you can understand. The former I don't have time for, and the latter is beyond my ability.

What you've said so far makes me think you're in over your head. You say stuff that makes little sense that I have to try to decipher, you have misconceived notions of words and concepts you're unwilling to reconsider (e.g. "I have to push these values on the shadow space" demonstrates a false understanding of "push" and "shadow space"), you don't understand or learn from other sources (msdn documentation, wikipedia articles, those blog posts), and you generally seem too focused on the goal without wanting to learn the stuff you need to get there.

Maybe it's just a language barrier- I don't know. I can't help you. I wish you good luck anyway.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
lawrenc3
Newbie cheater
Reputation: 0

Joined: 22 Mar 2020
Posts: 10

PostPosted: Sat Apr 03, 2021 4:28 pm    Post subject: Reply with quote

ParkourPenguin wrote:
I'm not going to write the code for you, and while I will link to the information you want, I'm not going to copy and paste it here for you in a format you can understand. The former I don't have time for, and the latter is beyond my ability.

What you've said so far makes me think you're in over your head. You say stuff that makes little sense that I have to try to decipher, you have misconceived notions of words and concepts you're unwilling to reconsider (e.g. "I have to push these values on the shadow space" demonstrates a false understanding of "push" and "shadow space"), you don't understand or learn from other sources (msdn documentation, wikipedia articles, those blog posts), and you generally seem too focused on the goal without wanting to learn the stuff you need to get there.

Maybe it's just a language barrier- I don't know. I can't help you. I wish you good luck anyway.


the real problem is that what those small pieces of code you wrote really say me nothing. I know I have to allocate space to the stack with “sub rsp,28” for the call. and then? how should I pass the args?
happy easter.
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 204

Joined: 25 Jan 2006
Posts: 8581
Location: 127.0.0.1

PostPosted: Sat Apr 03, 2021 6:35 pm    Post subject: This post has 1 review(s) Reply with quote

Based on your first few posts, I'd agree with ParkourPenguin that you are a bit over your head and trying to reach the goal without understanding the steps to get there. Your own posts are showing that you are not actually understanding how x64 works both with handling the stack, and with how the calling convention works. Along with that, you are making up assumptions on how things work and then being combative when being told/shown otherwise. If you are looking to actually learn, you need to take a step back and understand that you are going to be wrong, a lot of the time, when you first start. Rather than fight with someone trying to help you, take the time to lookup what they've presented and read about the topics.

You can find a full doc of how the x64, how its calling convention works, etc. on MSDN here:
https://docs.microsoft.com/en-us/cpp/build/x64-software-conventions?view=msvc-160
https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-160
https://docs.microsoft.com/en-us/cpp/build/stack-usage?view=msvc-160&viewFallbackFrom=vs-2019
https://docs.microsoft.com/en-us/cpp/build/prolog-and-epilog?view=msvc-160
https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64?view=msvc-160

Along with the Wikipedia article here:
https://en.wikipedia.org/wiki/X86_calling_conventions#x86-64_calling_conventions

Along with Intels article here:
https://software.intel.com/content/www/us/en/develop/articles/introduction-to-x64-assembly.html

Another few articles that helps show things with a visual aid:
https://www.ired.team/miscellaneous-reversing-forensics/windows-kernel-internals/x64-calling-convention-stack-frame
https://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64

Parameters passed via registers (ie. the first four) are allocated space on the stack. It's deeemed 'spill' space by Microsoft, who created the calling convention. It's not manditory to be used/populated at all either. It's used generally for debugging purposes as it gives compilers a pre-defined location to easily pass the 4 register params on the stack for easier debugging with certain tools etc. But that space is not required to be filled, cleared, populated, or ever used at all by either the caller or callee. It's just there in case it's needed. (This space on the stack has many various nicknames, be it 'shadow', 'spill', 'home space', etc.)

Keep in mind when looking up x64/AMD64 stuff, there are other variants of it that DO NOT follow these same standards.
This is specifically for the MS version of the standard / ABI. Another would be SystemV which does not have shadow space.

Shadow space is also not required for all functions. This is something you may want to look up/into in regards to leaf vs. non-leaf functions and how they handle the stack and shadow space in general.

lawrenc3 wrote:
we both have gaps in the argument also if we studied x64 asm and that's reasonable (this is a pretty hard argument to treat today - we don't need to often use asm today and finding good references about these things may get to become hard), still I didn't tell you to learn the basics just because you missed to tell me to push the args on the shadow space. it just happens, we are humans.


Sorry but I respectively disagree with this. There are plenty of docs around the x64 ABI, calling conventions, etc. and the ones already linked in this thread along with any I posted here are all easily found and go into great detail on how things work and what to expect. Be it you are not understanding things, or you are just straight up not reading them fully, that's not any fault to the information available.

There's tons of sites, articles, blogs, official docs for both Windows, Linux, ARM, etc. whom all implement x64 in their own manner, and so on that cover this. It's extremely easy to find info via Google regarding this.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
lawrenc3
Newbie cheater
Reputation: 0

Joined: 22 Mar 2020
Posts: 10

PostPosted: Sat Apr 03, 2021 7:23 pm    Post subject: Reply with quote

atom0s wrote:

There's tons of sites, articles, blogs, official docs for both Windows, Linux, ARM, etc. whom all implement x64 in their own manner, and so on that cover this. It's extremely easy to find info via Google regarding this.


dear atom0s, I am not “being combative” to anyone who tries to help me, it’s absolutely not from me. I just say what I know, if someone who is more advanced than me proves that I’m wrong it’s ok (this is why I opened the thread).
there are references that treat these concepts abstractly, and there are so many that these could mislead the ideas of who reads them.
shadow space is just for debugging purposes, could you show me a practical fix of the code above (I don’t need to allocate to rsp and do that)? I will understand better my error and I will know, while I reread msdn documentation, how to properly set up my call with the correct convention.

thanks.
Back to top
View user's profile Send private message
sbryzl
Master Cheater
Reputation: 6

Joined: 25 Jul 2016
Posts: 252

PostPosted: Sat Apr 03, 2021 9:38 pm    Post subject: Reply with quote

You've been waging debate against someone trying to help you with colloquial semantics you've found in an old blog. Debate would be fine if you knew what you're talking about but you've exhibited otherwise.
Nothing said to you here will prove anything to you. Ultimately the only way I think you can find the proof you want is by successful completion of your task. I would advise using the information and sources provided in this topic and the previous one and ignore the old blog with the different colloquial names for the same thing.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites