[Tutorial] Using functions from Windows libraries

Using windows libraries brings a lot of functionality to cleo. For example it allows to create an accurate FPS counter which wouldn't be possible using CLEO timers. Or things like setting the position and size of the GTA window, producing a beeping sound, retrieving current time and date. Potentially even executing a file (which I could never get to work properly).

How to call such functions in CLEO
If the function returns some value (0AA7):
Code:
0AA2: 0@ = load_library "kernel32.dll"
   if 0AA4: 1@ = get_proc_address "GetTickCount" library 0@
   then
   0AA7: call_function 1@ num_params 0 pop 0 2@

If the function doesn't return any value (0AA5):
Code:
0AA2: 0@ = load_library "kernel32.dll"
   if 0AA4: 1@ = get_proc_address "GetTickCount" library 0@
   then
   0AA5: call 1@ num_params 0 pop 0

GetTickCount doesn't require any input parameters but if it required it would look like this:
0AA7: ADDRESS_TO_CALL - PARAM_NUM - POP_NUM - SECOND_PARAM - FIRST_PARAM - RETURNED_VALUE
(The parameters passed should be in reverse order)
0AA7 - Opcode database
0AA7 - In depth explanation

For functions that do not return any value (e.g. "void SomeFunction(){}") it would look like:
0AA5: ADDRESS_TO_CALL - PARAM_NUM - POP_NUM - SECOND_PARAM - FIRST_PARAM
(The parameters passed should be in reverse order)
0AA5 - Opcode database

How to use push/pop parameter
Push - stands for number of arguments passed to function
Pop - without going into detail: if you know that it's WINAPI (stdcall) then set it to 0, if it's cdecl then set it to the same value as "push" parameter

Some functions take care themselves of "cleaning" parameters from stack, some functions don't take care of it and it has to be done outside of function after its return, that's what "pop" is doing.

Idk exactly how to find out the calling convention of specific function, would be good if someone clarified that and I'd update this section (link to theory , another link).

Resources for finding functions
I don't know if there's a list of all useful libraries with their most useful functions but you could check the following links:
-user32.dll
-shell32.dll (ShellExecute function is interesting, if anyone manages to make it work and posts it here it would be cool)
-kernel32.dll

Anyway I'd like to present a practical approach on how to effectively find and use them. Here's the example of what could be done to apply some function to solve FPS counter issue:
-type in google: "how to get tick count c++"
-notice the function "GetTickCount()" documented on msdn.microsoft.com Link
-notice the part of MSDN page which says: "Library Kernel32.lib", that's how to know which library to use in 0AA2 opcode
-notice the number and data type of parameters and returns to know how to call the function using 0AA7 opcode
-sometimes the return variable can't be null so it's important to read any remarks on the MSDN site

G9TNbbP.png
frDov5Q.png

Examples of usage
Make beep - by Opcode.eXe
Code:
//0AB1: @MAKE_BEEP 2 FREQUENCY 0x25 TIME 1000
:MAKE_BEEP
IF
0AA2: 31@ = load_library "kernel32.dll"
THEN
   IF
   0AA4: 30@ = get_proc_address "Beep" library 31@
   THEN
       0AA5: _CALL_ 30@ num_params 2 pop 0 1@ 0@
   END
   0AA3: free_library 31@
END
0AB2: 0

Set window position and size - by Opcode.eXe
Code:
0AB1: @SET_WINDOW_POS_AND_SIZE 4 pos_x 50 pos_y 40 width 400 width 400
:SET_WINDOW_POS_AND_SIZE
0A8D: 31@ = 0xC9C060 4 0
IF
31@ == TRUE
THEN
     0AA2: 30@ = load_library "User32.dll"
     0AA4: 29@ = get_proc_address "MoveWindow" library 30@
     0A8D: 28@ = 0xC97C1C 4 0
     0AA7: call_function 29@ params 6 pop 0 TRUE 3@ 2@ 1@ 0@ 28@ 29@
END
0AB2: 0


Get date and time
Code:
{$CLEO .cs}
0000:
repeat
wait 500
until 0AFA:  is_samp_available

alloc 30@ 256
call @Get_Date_Time 0 30@
chatmsg 30@ -1
free 30@

0A93: end_custom_thread




:Get_Date_Time
alloc 1@ 30
alloc 4@ 256
0AD3: 4@ = format "nodatefound"
0AA2: 2@ = load_library "kernel32.dll" // IF and SET
  if 0AA4: 3@ = get_proc_address "GetLocalTime" library 2@
  then
  0A8C: write_memory 1@ size 2 value 1 virtual_protect 1
  0AA5: call_function 3@ num_params 1 pop 0 1@
  //0AC7: 31@ = var 1@ offset
  0085: 31@ = 1@ // (int)

  0A8D: 20@ = read_memory 31@ size 2 virtual_protect 1
  31@ += 2
  0A8D: 21@ = read_memory 31@ size 2 virtual_protect 1
  31@ += 2
  0A8D: 22@ = read_memory 31@ size 2 virtual_protect 1
  31@ += 2
  0A8D: 23@ = read_memory 31@ size 2 virtual_protect 1
  31@ += 2
  0A8D: 24@ = read_memory 31@ size 2 virtual_protect 1
  31@ += 2
  0A8D: 25@ = read_memory 31@ size 2 virtual_protect 1
  31@ += 2
  0A8D: 26@ = read_memory 31@ size 2 virtual_protect 1
  //printf "%d %d %d %d %d %d %d" 2000 20@ 21@ 22@ 23@ 24@ 25@ 26@
  0AD3: 4@ = format "Day=%d Month=%d Year=%d Hour=%d Minute=%d Second=%d" 23@ 21@ 20@ 24@ 25@ 26@
  end
0AA3: free_library 2@
free 1@
0AB2: ret 1 4@


Time measurement
Code:
:halfSecondPassed
0AA2: 2@ = load_library "kernel32.dll" // IF and SET
   if 0AA4: 3@ = get_proc_address "GetTickCount" library 2@
   then
   0AA7: call_function 3@ num_params 0 pop 0 31@
   30@ = 0
   0085: 30@ = 31@ //
   0062: 30@ -= 0@  //
       if 0019:   30@ >= 500
       then
       0085: 0@ = 31@
       0485:  return_true
       else
       059A:  return_false
       end
   else
   059A:  return_false
   end
0AA3: free_library 2@
0AB2: ret 1 0@


Taking advantage of gta_sa.exe loading many functions at (seemingly) static addresses
You can do the following:
Code:
0A8D: 0@ = read_memory 0x858064 size 4 virtual_protect 0 // 0x858064 is an address where pointer to GetTickCount is stored
0AA7: call_function 0@ num_params 0 pop 0 1@
// we just called GetTickCount and stored the return to 1@

Code:
0AC8: 1@ = allocate_memory_size 20
0AD3: 1@ = format "hello world"
0A8D: 0@ = read_memory 0x8580DC size 4 virtual_protect 0 // 0x8580DC is an address where pointer to lstrlenA is stored
0AA7: call_function 0@ num_params 1 pop 0 string 1@ _returned_length 2@
// 2@ became the length of "hello world"

0x8582E4 - USER32.AdjustWindowRect
0x858268 - USER32.AdjustWindowRectEx
0x8582FC - USER32.ClientToScreen
0x858294 - USER32.ClipCursor
0x858078 - KERNEL32.CloseHandle
0x85834C - ole32.CoCreateInstance
0x858350 - ole32.CoInitialize
0x85822C - KERNEL32.CompareStringA
0x858230 - KERNEL32.CompareStringW
0x858354 - ole32.CoUninitialize
0x858120 - KERNEL32.CreateDirectoryA
0x85812C - KERNEL32.CreateEventA
0x8580A0 - KERNEL32.CreateFileA
0x858178 - KERNEL32.CreateFileMappingA
0x85817C - KERNEL32.CreateFileW
0x858188 - KERNEL32.CreateMutexA
0x8580BC - KERNEL32.CreateSemaphoreA
0x8580B4 - KERNEL32.CreateThread
0x8582E8 - USER32.CreateWindowExA
0x8582A4 - USER32.DefWindowProcA
0x8580E0 - KERNEL32.DeleteCriticalSection
0x8580F8 - KERNEL32.DeleteFileA
0x858024 - GDI32.DeleteObject
0x858270 - USER32.DestroyWindow
0x8582CC - USER32.DialogBoxParamA
0x8582C0 - USER32.DispatchMessageA
0x8582D0 - USER32.EndDialog
0x8580EC - KERNEL32.EnterCriticalSection
0x858050 - KERNEL32.EnumSystemLocalesA
0x85820C - KERNEL32.ExitProcess
0x8581D0 - KERNEL32.FatalAppExitA
0x858100 - KERNEL32.FindClose
0x85810C - KERNEL32.FindFirstFileA
0x858104 - KERNEL32.FindNextFileA
0x85816C - KERNEL32.FindResourceA
0x858170 - KERNEL32.FindResourceW
0x8582B4 - USER32.FindWindowA
0x8581C0 - KERNEL32.FlushFileBuffers
0x858198 - KERNEL32.FreeEnvironmentStringsA
0x85821C - KERNEL32.FreeEnvironmentStringsW
0x858110 - KERNEL32.FreeLibrary
0x858034 - KERNEL32.GetACP
0x858304 - USER32.GetClientRect
0x858148 - KERNEL32.GetCommandLineA
0x858058 - KERNEL32.GetCPInfo
0x858244 - KERNEL32.GetCurrentDirectoryA
0x858204 - KERNEL32.GetCurrentProcess
0x85818C - KERNEL32.GetCurrentProcessId
0x8580B0 - KERNEL32.GetCurrentThread
0x8581E8 - KERNEL32.GetCurrentThreadId
0x85805C - KERNEL32.GetDateFormatA
0x8580C0 - KERNEL32.GetDiskFreeSpaceA
0x8582D4 - USER32.GetDlgItem
0x858134 - KERNEL32.GetDriveTypeA
0x858250 - KERNEL32.GetEnvironmentStrings
0x858220 - KERNEL32.GetEnvironmentStringsW
0x858108 - KERNEL32.GetFileAttributesA
0x858074 - KERNEL32.GetFileSize
0x8581B4 - KERNEL32.GetFileType
0x85814C - KERNEL32.GetFullPathNameA
0x8582C8 - USER32.GetKeyboardLayout
0x8582B0 - USER32.GetKeyState
0x858094 - KERNEL32.GetLastError
0x858054 - KERNEL32.GetLocaleInfoA
0x858240 - KERNEL32.GetLocaleInfoW
0x85811C - KERNEL32.GetLocalTime
0x858138 - KERNEL32.GetLogicalDriveStringsA
0x858264 - USER32.GetMenu
0x858194 - KERNEL32.GetModuleFileNameA
0x858068 - KERNEL32.GetModuleHandleA
0x858030 - KERNEL32.GetOEMCP
0x858084 - KERNEL32.GetOverlappedResult
0x85806C - KERNEL32.GetProcAddress
0x8581F0 - KERNEL32.GetStartupInfoA
0x8581B8 - KERNEL32.GetStdHandle
0x858044 - KERNEL32.GetStringTypeA
0x858040 - KERNEL32.GetStringTypeW
0x858248 - KERNEL32.GetSystemDefaultLCID
0x858190 - KERNEL32.GetSystemDirectoryA
0x858158 - KERNEL32.GetSystemInfo
0x858200 - KERNEL32.GetSystemTimeAsFileTime
0x8580AC - KERNEL32.GetThreadPriority
0x858064 - KERNEL32.GetTickCount
0x858228 - KERNEL32.GetTimeFormatA
0x858238 - KERNEL32.GetTimeZoneInformation
0x858124 - KERNEL32.GetUserDefaultLCID
0x858144 - KERNEL32.GetVersionExA
0x858130 - KERNEL32.GetVolumeInformationA
0x858260 - USER32.GetWindowLongA
0x85828C - USER32.GetWindowPlacement
0x8582F0 - USER32.GetWindowRect
0x858140 - KERNEL32.GlobalMemoryStatus
0x8581F8 - KERNEL32.HeapAlloc
0x8581AC - KERNEL32.HeapCreate
0x8581B0 - KERNEL32.HeapDestroy
0x8581FC - KERNEL32.HeapFree
0x8581F4 - KERNEL32.HeapReAlloc
0x8581D8 - KERNEL32.HeapSize
0x8580F0 - KERNEL32.InitializeCriticalSection
0x8580D0 - KERNEL32.InterlockedDecrement
0x858218 - KERNEL32.InterlockedExchange
0x8580CC - KERNEL32.InterlockedIncrement
0x858038 - KERNEL32.IsBadCodePtr
0x85803C - KERNEL32.IsBadReadPtr
0x8581A0 - KERNEL32.IsBadWritePtr
0x85825C - USER32.IsIconic
0x85815C - KERNEL32.IsProcessorFeaturePresent
0x858048 - KERNEL32.IsValidCodePage
0x85804C - KERNEL32.IsValidLocale
0x8581C8 - KERNEL32.LCMapStringA
0x8581C4 - KERNEL32.LCMapStringW
0x8580E8 - KERNEL32.LeaveCriticalSection
0x858280 - USER32.LoadCursorA
0x85827C - USER32.LoadIconA
0x858070 - KERNEL32.LoadLibraryA
0x858164 - KERNEL32.LoadResource
0x8580B8 - KERNEL32.LocalAlloc
0x85807C - KERNEL32.LocalFree
0x858160 - KERNEL32.LockResource
0x8580D8 - KERNEL32.lstrcatA
0x858154 - KERNEL32.lstrcmpiA
0x8580D4 - KERNEL32.lstrcpyA
0x8580DC - KERNEL32.lstrlenA
0x858174 - KERNEL32.MapViewOfFile
0x8582A8 - USER32.MapVirtualKeyA
0x8582F4 - USER32.MessageBoxA
0x824570 - <ModuleEntryPoint>
0x8580F4 - KERNEL32.MultiByteToWideChar
0x858118 - KERNEL32.OutputDebugStringA
0x858360 - vorbisfile.ov_clear
0x858370 - vorbisfile.ov_info
0x85835C - vorbisfile.ov_open_callbacks
0x85836C - vorbisfile.ov_read
0x858374 - vorbisfile.ov_time_seek
0x858368 - vorbisfile.ov_time_tell
0x858364 - vorbisfile.ov_time_total
0x8582BC - USER32.PeekMessageA
0x858298 - USER32.PostQuitMessage
0x8580C8 - KERNEL32.QueryPerformanceCounter
0x858114 - KERNEL32.QueryPerformanceFrequency
0x858214 - KERNEL32.RaiseException
0x858098 - KERNEL32.ReadFile
0x858000 - ADVAPI32.RegCloseKey
0x858004 - ADVAPI32.RegCreateKeyExA
0x858284 - USER32.RegisterClassA
0x858010 - ADVAPI32.RegOpenKeyA
0x858008 - ADVAPI32.RegOpenKeyExA
0x85800C - ADVAPI32.RegQueryValueExA
0x858014 - ADVAPI32.RegSetValueExA
0x858288 - USER32.ReleaseCapture
0x858184 - KERNEL32.ReleaseMutex
0x85808C - KERNEL32.ReleaseSemaphore
0x8580A4 - KERNEL32.ResumeThread
0x858210 - KERNEL32.RtlUnwind
0x8582DC - USER32.SendMessageA
0x8582A0 - USER32.SetCapture
0x858224 - KERNEL32.SetConsoleCtrlHandler
0x85824C - KERNEL32.SetCurrentDirectoryA
0x85829C - USER32.SetCursor
0x858300 - USER32.SetCursorPos
0x85823C - KERNEL32.SetEndOfFile
0x858234 - KERNEL32.SetEnvironmentVariableA
0x85813C - KERNEL32.SetErrorMode
0x858090 - KERNEL32.SetFilePointer
0x8582D8 - USER32.SetFocus
0x8582B8 - USER32.SetForegroundWindow
0x8581BC - KERNEL32.SetHandleCount
0x85809C - KERNEL32.SetLastError
0x858128 - KERNEL32.SetStdHandle
0x8580A8 - KERNEL32.SetThreadPriority
0x858290 - USER32.SetTimer
0x8581D4 - KERNEL32.SetUnhandledExceptionFilter
0x858274 - USER32.SetWindowLongA
0x8582E0 - USER32.SetWindowPos
0x8582F8 - USER32.SetWindowTextA
0x8582EC - USER32.ShowCursor
0x858278 - USER32.ShowWindow
0x858168 - KERNEL32.SizeofResource
0x8580C4 - KERNEL32.Sleep
0x8580E4 - KERNEL32.SuspendThread
0x85826C - USER32.SystemParametersInfoA
0x858208 - KERNEL32.TerminateProcess
0x8580FC - KERNEL32.TerminateThread
0x858314 - WINMM.timeBeginPeriod
0x85830C - WINMM.timeEndPeriod
0x858318 - WINMM.timeGetDevCaps
0x858310 - WINMM.timeGetTime
0x8581DC - KERNEL32.TlsAlloc
0x8581EC - KERNEL32.TlsFree
0x8581E0 - KERNEL32.TlsGetValue
0x8581E4 - KERNEL32.TlsSetValue
0x8582C4 - USER32.TranslateMessage
0x85819C - KERNEL32.UnhandledExceptionFilter
0x858180 - KERNEL32.UnmapViewOfFile
0x8582AC - USER32.UpdateWindow
0x8581A4 - KERNEL32.VirtualAlloc
0x8581A8 - KERNEL32.VirtualFree
0x85802C - KERNEL32.VirtualProtect
0x858060 - KERNEL32.VirtualQuery
0x858088 - KERNEL32.WaitForSingleObject
0x858080 - KERNEL32.WaitForSingleObjectEx
0x858150 - KERNEL32.WideCharToMultiByte
0x8581CC - KERNEL32.WriteFile
0x858258 - USER32.wsprintfA

How to find these:
Download OllyDbg1.1 and open it as administrator, run and minimize samp, click "File -> Attach" and pick gta_sa. Click "View -> Executable modules", find "gta_sa" and double click it. The "CPU" window will get focus, right click it and select "Search for -> Name (label) in current module". The list should appear. You can also select "Name in all modules" which will show you really big list of functions (but these require using "0AA2: load library" and "0AA4: get_proc_address" opcodes unlike the ones imported to gta_sa.exe).[/SPOILER]
 
Last edited:

Opcode.eXe

Expert
Joined
Feb 18, 2013
Messages
1,486
Reaction score
227
Location
( ͡° ͜ʖ ͡°)
When you use: "Beep" with 1000ms beep time your gta_sa will also freeze for the duration of it.
Thats one of the bad sideeffects of the functions :X
 
Joined
Feb 18, 2005
Messages
2,963
Reaction score
267
Nice. Here's ShellExecute example.

[shcode=cpp]
0AA2: 0@ = "shell32.dll"
IF 0AA4: 0@ = "ShellExecuteA" 0@
THEN
   0AA7: 0@ push 6 pop 1 params 1 0 0 "www.ugbase.eu" 0 0 error_code 1@
   IF 1@ <= 32
   THEN PRINTF "FAILURE: %d" 1000 1@
   END
END
[/shcode]
 

Strechea

Active member
Joined
Jan 26, 2017
Messages
28
Reaction score
2
hey, i tried this but i don't know why it doesn't work....
{$CLEO}
0000:
repeat
wait 0
until 0afa:
0b63: "fileinfo"
0b34: "fileinfo" @fileinfo
while true
wait 0
end
:fileinfo
0b35: 11@
11@ = File.Open(10@, "rt")
/*

BOOL WINAPI GetFileTime(
_In_ HANDLE hFile,
_Out_opt_ LPFILETIME lpCreationTime,
_Out_opt_ LPFILETIME lpLastAccessTime,
_Out_opt_ LPFILETIME lpLastWriteTime
);
*/
alloc 12@ 260
alloc 13@ 260
alloc 14@ 260
alloc 15@ 260
call @getFileInfo 1 fileHandle 11@ results-> lpCreationTime 12@ lpLastAccesTime 13@ lpLastWriteTime 14@
format 15@ "lpCreationTime %s lpLastAccesTime %s lpLastWriteTime %s" 12@ 13@ 14@
chatmsg 15@ -1
File.Close(11@)
cmdret



:getFileInfo
0AA2: 2@ = load_library "kernel32.dll" // IF and SET
if 0AA4: 3@ = get_proc_address "GetFileTime" library 2@
then
0AA7: call_function 3@ num_params 1 pop 0 0@ 5@ 6@ 7@
end
0AA3: free_library 2@
0AB2: ret 3 5@ 6@ 7@


@monday can u help me please?
 

shanker

Well-known member
Joined
Sep 18, 2016
Messages
291
Reaction score
16
Location
Romania
springfield said:
Nice. Here's ShellExecute example.

[shcode=cpp]
0AA2: 0@ = "shell32.dll"
IF 0AA4: 0@ = "ShellExecuteA" 0@
THEN
   0AA7: 0@ push 6 pop 1 params 1 0 0 "www.ugbase.eu" 0 0 error_code 1@
   IF 1@ <= 32
   THEN PRINTF "FAILURE: %d" 1000 1@
   END
END
[/shcode]

can you tell me why this version[v1] don't give any avertisment of crassh and that one[v2] do

[v1]
[shcode=cpp]
{$CLEO}

0000:

repeat
wait 0
until 0AFA:

0B34: "Test" to @TEST

while true
   wait 0
end

:TEST
0AA2: 0@ = "shell32.dll"
IF 0AA4: 0@ = "ShellExecuteA" 0@
THEN
  0AA7: 0@ push 6 pop 1 params 1 0 0 "www.ugbase.eu" 0 0 error_code 1@
  IF 1@ <= 32
  THEN PRINTF "FAILURE: %d" 1000 1@
  END
END
cmdret
// it don't give me warnings
[/shcode]

[v2]
[shcode=cpp]
{$CLEO}

0000:

repeat
wait 0
until 0AFA:


0AB1: @TEST 0  // or gosub but stil gives crash, happening same if i just add the source to be readed without any jump funcs

while true
wait 0
end

:TEST
0AA2: 0@ = "shell32.dll"
IF 0AA4: 0@ = "ShellExecuteA" 0@
THEN
  0AA7: 0@ push 6 pop 1 params 1 0 0 "www.ugbase.eu" 0 0 error_code 1@
  IF 1@ <= 32
  THEN PRINTF "FAILURE: %d" 1000 1@
  END
END
ret 0
// this mdfk give warning
[/shcode]
 

Strechea

Active member
Joined
Jan 26, 2017
Messages
28
Reaction score
2
What do you do in case you have a Struct as return value?
In case of:


:getCurrentHWiD
0AA2: 0@ = load_library "Advapi32.dll"
if 0AA4: 1@ = get_proc_address "GetCurrentHwProfileW" library 0@
then
0AA7: call_function 1@ num_params 0 pop 0 2@
end
ret 0

it does return the value but as a structure, how do you read it?
 
Top