Calling Windows APIs
Due playing with MS-Windows Exploitation development, I was using some C applications that calling Windows APIs and I wanted to give it a try and take it step by step.
The simplest example came to my mind is calling the MessageBoxA function. If we take a look at the MSDN of MessageBoxA function, we'll find at very beginning the function description and its arguments and returns. At the Requirements section, we'll find the required DLL to call MessageBoxA function which is User32.dll library.
1
int WINAPI MessageBox(
2
_In_opt_ HWND hWnd,
3
_In_opt_ LPCTSTR lpText,
4
_In_opt_ LPCTSTR lpCaption,
5
_In_ UINT uType
6
);
Copied!
Let's do it,
1
require "Win32API"
2
3
title = "Rubyfu!"
4
message = "You've called the Windows API Successfully! \n\[email protected]"
5
6
api = Win32API.new('user32', 'MessageBoxA',['L', 'P', 'P', 'L'],'I')
7
api.call(0,message,title,0)
Copied!
That's was really easy! but, Win32API is going to be deprecated or it's already deprecated at the moment you read this part. Ruby have moved all dealing with C, dll functions to Fiddle class which is a wrapper of libffi C library which provides a portable interface to allow languages to call code from another language.
If we build our MessageBoxA script again using Fiddle it will be like
1
# Load importer part of fiddle (ffi) library
2
require 'fiddle/import'
3
4
# int WINAPI MessageBox(
5
# _In_opt_ HWND hWnd,
6
# _In_opt_ LPCTSTR lpText,
7
# _In_opt_ LPCTSTR lpCaption,
8
# _In_ UINT uType
9
# );
10
# Create module as body for an importer instance
11
module User32
12
# Extend this module to an importer
13
extend Fiddle::Importer
14
# Load 'user32' dynamic library into this importer
15
dlload 'user32'
16
# Set C aliases to this importer for further understanding of function signatures
17
typealias 'HWND', 'HANDLE'
18
typealias 'LPCSTR', 'const char*'
19
typealias 'LPCWSTR', 'const wchar_t*'
20
typealias 'UINT', 'unsigned int'
21
typealias 'HANDLE', 'void*'
22
# Import C functions from loaded libraries and set them as module functions
23
extern 'int MessageBoxA(HWND, LPCSTR, LPCSTR, UINT)'
24
end
25
26
title = "Rubyfu!"
27
message = "You've called the Windows API Successfully! \n\[email protected]"
28
User32::MessageBoxA(nil, message, title, 0)
Copied!
Source
As you can the script is getting much bigger but, important thing to mention is, Using Win32API is going to be a real pain for bigger or more complicated tasks, in another hand Fiddle is more elegant and readable than Win32API
At that point, I was wondering if I can write something like an old frind application call arwin which finds a Function location in a Windows library. With the help of MSDN [LoadLibrary](https://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85.aspx) and [GetProcAddress](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85.aspx) documentations let's do it.
arwin.rb
1
require 'fiddle/import'
2
#
3
# KING SABRI | @KINGSABRI
4
#
5
if ARGV.size == 2
6
lpfilename = ARGV[0] # Library Name
7
lpprocname = ARGV[1] # Function Name
8
else
9
puts "ruby arwin.rb <Library Name> <Function Name>"
10
puts "example:\n arwin.rb user32.dll MessageBoxA"
11
exit 0
12
end
13
14
15
module Kernel32
16
17
# Extend this module to an importer
18
extend Fiddle::Importer
19
# Load 'user32' dynamic library into this importer
20
dlload 'kernel32'
21
22
# HMODULE WINAPI LoadLibrary(
23
# _In_ LPCTSTR lpFileName
24
# );
25
typealias 'lpfilename', 'char*'
26
extern 'unsigned char* LoadLibrary(lpfilename)'
27
28
# FARPROC WINAPI GetProcAddress(
29
# _In_ HMODULE hModule,
30
# _In_ LPCSTR lpProcName
31
# );
32
typealias 'lpfilename', 'char*'
33
typealias 'lpprocname', 'char*'
34
extern 'unsigned char* GetProcAddress(lpfilename, lpprocname)'
35
36
end
37
address = Kernel32::GetProcAddress(Kernel32::LoadLibrary(lpfilename), lpprocname).inspect.scan(/0x[\h]+/i)[1]
38
unless address.hex.zero?
39
puts "\n[+] #{lpprocname} is location at #{address} in #{lpfilename}\n"
40
else
41
puts "[!] Could find #{lpprocname} in #{lpfilename}!"
42
puts "[-] Function's name is case sensitive"
43
end
Copied!
Results
1
[+] MessageBoxA is location at 0x77d8050b in user32.dll
Copied!
Last modified 3yr ago
Copy link