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 


Make a beep in auto-assembly?

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Discussions
View previous topic :: View next topic  
Author Message
deama1234
Master Cheater
Reputation: 3

Joined: 20 Dec 2014
Posts: 328

PostPosted: Thu Feb 05, 2015 4:11 pm    Post subject: Make a beep in auto-assembly? Reply with quote

Well, I tried to "call beep" but that just crashes it whenever I press the button which has the "call beep" bit in it.

This documentation is interesting, but confuses me, because "I don't know how to read it".
https://msdn.microsoft.com/en-us/library/windows/desktop/ms679277%28v=vs.85%29.aspx

there's no eax's or ecx's or general auto-assembly stuff I know, so...
Back to top
View user's profile Send private message
SteveAndrew
Master Cheater
Reputation: 30

Joined: 02 Sep 2012
Posts: 323

PostPosted: Fri Feb 06, 2015 5:24 am    Post subject: Re: Make a beep in auto-assembly? This post has 2 review(s) Reply with quote

deama1234 wrote:
Well, I tried to "call beep" but that just crashes it whenever I press the button which has the "call beep" bit in it.

This documentation is interesting, but confuses me, because "I don't know how to read it".
https://msdn.microsoft.com/en-us/library/windows/desktop/ms679277%28v=vs.85%29.aspx

there's no eax's or ecx's or general auto-assembly stuff I know, so...


Ok well there wont be any assembler stuff there as it's a c++ reference, but that doesn't mean it's not helpful. The best way to see what you need to do in assembler is by looking code that works with cheat engine and debugging it. It isn't always necessary though like in this case.

Since you mentioned eax and ecx rather than rax and rcx I'm answering this question as it relates to 32-bit assembler. 64-bit has only one calling convention and is a bit different (parameters are passed via registers, then the stack, rather than only the stack)

Firstly we have:
Code:

BOOL WINAPI Beep(
  _In_  DWORD dwFreq,
  _In_  DWORD dwDuration
);


We can see that the return value for kernel32.Beep is a boolean. BOOL type in x86 c++ is a 32-bit data type which is either true or false, 1 or 0. WINAPI is just a typedef for __stdcall. An stdcall calling convention means the callee (API/Function being called) is the one responsible for cleaning up the stack as we'll see in a bit.

The return value ends up in the eax register. The return value basically always will be written to eax before the API/Function cleans up the stack (if it's __stdcall) and returns. ("ret / retn")

You need to push the parameters into the stack in reverse order. So the first parameter "dwFreq" will be pushed last, while the last parameter "dwDuration" will be pushed first.

pseudo code:
Code:

push dwDuration
push dwFreq
call kernel32.Beep
.if eax == 1
 Success
.elseif eax == 0
 Failure
.endif



The example given is "Beep( 750, 300 );" A 750 hertz frequency for 300 milliseconds. So let's get that c++ code line written as auto assembler code instead.
It also mentions using the MessageBeep api instead so let's also do that one.

Code:

[enable]
alloc(BeepTest,1024)
label(BeepSucceeded)
label(BeepFailed)
label(MessageBeepSucceeded)
label(MessageBeepFailed)
label(BeepTestExit)
label(BeepReturnValue)
label(MessageBeepReturnValue)
registersymbol(BeepTest)
registersymbol(BeepReturnValue)
registersymbol(MessageBeepReturnValue)
createthread(BeepTest)

BeepTest:
push #300
push #750
call kernel32.Beep
test eax,eax
jne BeepSucceeded
jmp BeepFailed

BeepSucceeded:
mov [BeepReturnValue],eax

BeepFailed:
push FFFFFFFF
call user32.MessageBeep
test eax,eax
jne MessageBeepSucceeded
jmp MessageBeepFailed

MessageBeepSucceeded:
mov [MessageBeepReturnValue],eax

MessageBeepFailed:
BeepTestExit:
ret

BeepReturnValue:
dd 0
MessageBeepReturnValue:
dd 0


[disable]

dealloc(BeepTest)
unregistersymbol(BeepTest)
unregistersymbol(BeepReturnValue)
unregistersymbol(MessageBeepReturnValue)



Upon attaching to any 32-bit application, and enabling the script (after added to CT), you'll hear two beeps (Beep, then MessageBeep) if they were successful and it looks like this after you go to address "BeepTest"



In my case both succeeded and I heard both, with the return values equaling 1 / true. (success == true)


Lets go over some of the code:
Code:

push #300 //300 milliseconds
push #750 //750 hertz
call kernel32.Beep //calling the Beep api
test eax,eax //checking eax for zero


after the "test eax,eax" line: A je would be eax is equal to zero (unsuccessful), and a jne (as shown in the example) would be eax is a nonzero value. (successful)

I think your code is crashing likely because when the call to kernel32.Beep returns it's popping off those two parameters when you either haven't pushed them, or pushed them incorrectly.

Let's try a more complicated win32 api maybe a few combined just so you have this down solid.

Here I did something pretty pointless as CE can allocate all the memory we need, but I just wanted to demonstrate how you can use those microsoft c++ reference pages to get help at calling virtually any windows api in assembler or auto assembler!

This code upon being enabled, creates a thread that first allocates 1KB of memory, then if successful gets your logged in user's username and if successful, displays it in a message box. Once the message box is closed, or if getting the username failed the memory allocated initially is released and the thread then exits.
Code:

[enable]
alloc(AllocGetUsernameDeallocTest,1024)
label(DeallocAndExitTest)
label(ExitTest)
label(pManuallyAllocatedMemory)
label(pUsernameLength)
label(pCaption)
registersymbol(AllocGetUsernameDeallocTest)
registersymbol(pManuallyAllocatedMemory)
createthread(AllocGetUsernameDeallocTest)

AllocGetUsernameDeallocTest:
push 40 //PAGE_EXECUTE_READWRITE
push 1000 //MEM_COMMIT
push #1024 //1024 bytes
push 0 //optional, make it null
call kernel32.VirtualAlloc
test eax,eax
je ExitTest //jmp is followed if allocation failed
mov [pManuallyAllocatedMemory],eax

push pUsernameLength //buffer length at this point
push eax //[pManuallyAllocatedMemory]
call advapi32.GetUserNameA //A version / non unicode
test eax,eax
je DeallocAndExitTest //jmp is followed if getting username failed

//here pUsernameLength is now the size of string
//returned to [pManuallyAllocatedMemory]
push 30 //MB_ICONEXCLAMATION
push pCaption
push [pManuallyAllocatedMemory] //[] value because the value is a pointer
push 0 //HWND, null is fine
call user32.MessageBoxA

DeallocAndExitTest:
push 8000 //MEM_RELEASE
push 0 //must be zero if MEM_RELEASE
push [pManuallyAllocatedMemory] //pointer to memory to be free'd
call kernel32.VirtualFree

ExitTest:
ret


pManuallyAllocatedMemory:
dd 0
pUsernameLength:
dd #1024
pCaption:
db 'Username:',0


[disable]

dealloc(AllocGetUsernameDeallocTest)
unregistersymbol(AllocGetUsernameDeallocTest)
unregistersymbol(pManuallyAllocatedMemory)


References Used:
VirtualAlloc->https://msdn.microsoft.com/en-us/library/windows/desktop/aa366887(v=vs.85).aspx
GetUsernameA->https://msdn.microsoft.com/en-us/library/windows/desktop/ms724432(v=vs.85).aspx
MessageBoxA->https://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=vs.85).aspx
VirtualFree->https://msdn.microsoft.com/en-us/library/windows/desktop/aa366892(v=vs.85).aspx

After enabled:


After message box closed:


Of course you could've just used CE to allocate the memory used and you could've shortened it a bit. The point was though just to show more of an example than just Beep / MessageBeep!

So do you understand how to call Windows API's from auto assembler now? Smile

_________________
Back to top
View user's profile Send private message
deama1234
Master Cheater
Reputation: 3

Joined: 20 Dec 2014
Posts: 328

PostPosted: Fri Feb 06, 2015 10:36 am    Post subject: Reply with quote

Yes, it makes more sense now, thanks.
Though, what is this "registersymbol(BeepReturnValue)"?

EDIT: I got another question: can I create a thread in the middle of execution?
So...
Psudocode:

Code:
sub [ebx+00000480],eax  /*it runs this then goes to the beep
    push #1000                         *but how do I make it run this AND go past it?
    push #150                          *Kinda like creating a thread just to run the
call kernel32.Beep                   *beep. I tried doing this but it runs it when I
                                             */Enable the script...
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Discussions All times are GMT - 6 Hours
Page 1 of 1

 
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