 |
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
lawrenc3 Newbie cheater
Reputation: 0
Joined: 22 Mar 2020 Posts: 10
|
Posted: Fri Apr 02, 2021 8:26 pm Post subject: (continue of...) calling function doesn't work |
|
|
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 |
|
 |
ParkourPenguin I post too much
Reputation: 150
Joined: 06 Jul 2014 Posts: 4657
|
Posted: Fri Apr 02, 2021 9:29 pm Post subject: |
|
|
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 |
|
 |
lawrenc3 Newbie cheater
Reputation: 0
Joined: 22 Mar 2020 Posts: 10
|
Posted: Fri Apr 02, 2021 9:54 pm Post subject: |
|
|
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 |
|
 |
ParkourPenguin I post too much
Reputation: 150
Joined: 06 Jul 2014 Posts: 4657
|
Posted: Sat Apr 03, 2021 12:15 am Post subject: |
|
|
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 |
|
 |
lawrenc3 Newbie cheater
Reputation: 0
Joined: 22 Mar 2020 Posts: 10
|
Posted: Sat Apr 03, 2021 7:31 am Post subject: |
|
|
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 |
|
 |
Oxijen Expert Cheater
Reputation: 0
Joined: 07 May 2020 Posts: 163 Location: On The Moon
|
Posted: Sat Apr 03, 2021 10:59 am Post subject: |
|
|
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  |
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 150
Joined: 06 Jul 2014 Posts: 4657
|
Posted: Sat Apr 03, 2021 11:13 am Post subject: |
|
|
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 ... |
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 |
|
 |
lawrenc3 Newbie cheater
Reputation: 0
Joined: 22 Mar 2020 Posts: 10
|
Posted: Sat Apr 03, 2021 11:52 am Post subject: |
|
|
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 |
|
 |
ParkourPenguin I post too much
Reputation: 150
Joined: 06 Jul 2014 Posts: 4657
|
Posted: Sat Apr 03, 2021 12:44 pm Post subject: |
|
|
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 |
|
 |
lawrenc3 Newbie cheater
Reputation: 0
Joined: 22 Mar 2020 Posts: 10
|
Posted: Sat Apr 03, 2021 2:39 pm Post subject: |
|
|
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 |
|
 |
ParkourPenguin I post too much
Reputation: 150
Joined: 06 Jul 2014 Posts: 4657
|
Posted: Sat Apr 03, 2021 4:11 pm Post subject: |
|
|
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 |
|
 |
lawrenc3 Newbie cheater
Reputation: 0
Joined: 22 Mar 2020 Posts: 10
|
Posted: Sat Apr 03, 2021 4:28 pm Post subject: |
|
|
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 |
|
 |
atom0s Moderator
Reputation: 204
Joined: 25 Jan 2006 Posts: 8581 Location: 127.0.0.1
|
Posted: Sat Apr 03, 2021 6:35 pm Post subject: |
|
|
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 |
|
 |
lawrenc3 Newbie cheater
Reputation: 0
Joined: 22 Mar 2020 Posts: 10
|
Posted: Sat Apr 03, 2021 7:23 pm Post subject: |
|
|
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 |
|
 |
sbryzl Master Cheater
Reputation: 6
Joined: 25 Jul 2016 Posts: 252
|
Posted: Sat Apr 03, 2021 9:38 pm Post subject: |
|
|
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 |
|
 |
|
|
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
|
|