Get signatures of exported functions of a system DLL - c

How do you get the signature of an exported function of a DLL? I know this is possible since a program analysis tool such as IDA (and ollydbg) manages to get the following for GetVersionExA:
push offset VersionInformation ; lpVersionInformation
mov edi, offset dword_4D3B94
mov esi, offset aSS ; "%s - %s"
call GetVersionExA
Using a hex editor to search through PDBs, I could not find the string lpVersionInformation. So where and how can I extract the signature?

Related

Stuck on porting OpenGL API loader implemented by 64-bit masm to that implemented by 32-bit

I am recently porting a OpenGL API loader implemented by 64-bit masm to that of 32-bit, part of 64-bit source codes are as follows:
.code
extrn __blue_glCore_glMultiDrawArraysIndirectBindlessCountNV: qword
glMultiDrawArraysIndirectBindlessCountNV proc
mov r11, __blue_glCore_glMultiDrawArraysIndirectBindlessCountNV
jmp r11
glMultiDrawArraysIndirectBindlessCountNV endp
extrn __blue_glCore_glCopyTexImage1D: qword
glCopyTexImage1D proc
mov r11, __blue_glCore_glCopyTexImage1D
jmp r11
glCopyTexImage1D endp
...
e.g. external symbol __blue_glCore_glMultiDrawArraysIndirectBindlessCountNV will be load when calling glMultiDrawArraysIndirectBindlessCountNV. My 32-bit modifications(change all qword to dword, all r11 to eax) are:
.model flat
.code
extrn __blue_glCore_glMultiDrawArraysIndirectBindlessCountNV: dword
glMultiDrawArraysIndirectBindlessCountNV proc
mov eax, __blue_glCore_glMultiDrawArraysIndirectBindlessCountNV
jmp eax
glMultiDrawArraysIndirectBindlessCountNV endp
extrn __blue_glCore_glCopyTexImage1D: dword
glCopyTexImage1D proc
mov eax, __blue_glCore_glCopyTexImage1D
jmp eax
glCopyTexImage1D endp
When other targets link this loader during compilation, the compiler(I used Visual Studio 2019) complains unresolved external symbol error. I actually know little about MASM, who can help me out?
Update1
I have created a mini demo in this repo to reproduce this problem, which can be built directly with Visual Studio and cmake. In particular, these lines puzzle me:
GLint major = 0, minor = 0;
//these two symbol are found
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
//this symbol is missed
glActiveTexture(0);
why only symbols of opengl1.0 and 1.1(opengl32.lib) loaded while others missed?
Update2
My Visual Studio linker complains:
Severity Code Description Project File Line Suppression State
Error LNK1120 1 unresolved externals test_bluegl E:\CPPCode\projects\bluegl\build\Debug\test_bluegl.exe 1
Error LNK2019 unresolved external symbol _glActiveTexture#4 referenced in function "private: virtual void __thiscall bluegl::BlueGLTest_GetVersion_Test::TestBody(void)" (?TestBody#BlueGLTest_GetVersion_Test#bluegl##EAEXXZ) test_bluegl E:\CPPCode\projects\bluegl\build\test_bluegl.obj 1
then I use dumpbin.exe to check generated symbol in bluegl.lib:
...
55DF0 _glActiveTexture#0
...
So I changed the corresponding proc to:
extrn __blue_glCore_glActiveTexture: dword
glActiveTexture proc param : dword
mov edx, __blue_glCore_glActiveTexture
jmp edx
glActiveTexture endp
Now the generated symbol was right and linking is OK, but new problems arose:
Visual Studio will report:
Severity Code Description Project File Line Suppression State
Error LNK2026 module unsafe for SAFESEH image. test_bluegl E:\CPPCode\projects\bluegl\build\bluegl.lib(BlueGLCoreWindowsImpl.obj) 1
Error LNK1281 Unable to generate SAFESEH image. test_bluegl E:\CPPCode\projects\bluegl\build\Debug\test_bluegl.exe 1
without setting /safeseh property for the masm source.
2 It's too heavy to append parameter list for each api, and I don't know why 64-bit masm not requiring parameter list.
Select a C implementation as workaround, but still interested in a masm32 implementation.

C Inline Asm Int 0x10

I'm attempting to write a function that prints strings the screen in C. It's for a boot loader so there are no external libraries or anything linked in. Here's my function:
void printString(const char* pStr) {
while(*pStr) {
__asm__ __volatile__ (
"movb 0x0e, %%ah\n"
"movb %[c], %%al\n"
"int $0x10\n"
:
: [c] "r" (*pStr)
: "ax"
);
++pStr;
}
}
When I run this, I don't get any errors in my VM. It just sits there with the cursor in the upper left corner of the screen. Any thoughts? I can produce an objdump -d if anyone thinks it will be helpful.
Okay after some helpful comments, I may just go with full assembly. Something like
Print:
push %ax
movb $0x0E, %ah # Set interrupt code
movb $0x00, %bh # Set page #
.loop:
lodsb # Load next char
test %al, %al # Check for \0
je .done
int $0x10 # Call interrupt
jmp .loop
.done:
pop %ax
ret
That should be 16-bit real mode compatible and can be assembled with GAS, which, as I understand it, works better than GCC for compiling 16-bit programs.
I think you're missing the point. The problem isn't your assembly code; the problem is that "int 10" is a BIOS
If you've already booted to an OS (e.g. Windows or Linux), then your x86 CPU is running in "protected mode"; and you probably don't have access to int 10 from user space ... unless something like a Windows command prompt emulates it for you.
As far as Linux/assembly programming in general, I strongly recommend this (free, on-line, very good) book:
Programming from the Ground Up, Jonathan Bartlett
Thank you for clarifying that you're writing a "boot loader". Strong suggestion1: boot your custom code from a USB stick, or create a virtual DOS floppy to boot a DOS VM (either VMWare or VBox VMs, for example).
Here are some tutorials:
http://www.codeproject.com/Articles/36907/How-to-develop-your-own-Boot-Loader
https://cs.au.dk/~sortie/dopsys/osdev/
http://wiki.osdev.org/Rolling_Your_Own_Bootloader

How to write inline assembly in FreeDOS

I'm trying to write the following program to dump the interrupt vector table using FreeDOS in a virtual machine. I know that DEBUG will allow me to write an assembly program, but how do I create the following IVTDUMP.COM file, save it and run it?
Note: I'd like to try and do it all straight from FreeDOS if possible. I tried using the EDIT command but it errors out and I'm pretty sure I'm missing something.
for
(
address=IDT_255_ADDR;
address>=IDT_001_ADDR;
address=address-IDT_VECTOR_SZ,vector--
)
{
printf("%03d %08p ",vector,address);
__asm
{
PUSH ES
MOV AX,0
MOV ES,AX
MOV BX,address
MOV AX,ES:[BX]
MOV ipAddr,AX
INC BX
INC BX
MOV AX,ES:[BX]
MOV csAddr,AX
POP ES
};
printf("[CS:IP]=[%04X,%04X]\n",csAddr,ipAddr);
}
Things like for, address and printf are not part of assembly. You will have to rewrite that to actual assembly code or copy the macros and assembler you want to use to your freedos environment.
If you want to use debug as included in freedos you can use the a command to start writing assembly instructions, the n command to give a name and w to write the code to the file.
C:\debug
-a
06BC:0100 int 20
06BC:0102
-n ivtdump.com
-rcx 2
-w
Writing 0002 bytes.
-q
C:\
This sample program only exits the program through int 20. (The 2 after rcx indicates the length of the program to write to disk)

how to create .com files using masm 5.10?

.model tiny
.code
org 100h
host:
mov ah,9
mov dx,offset hi
int 21h
mov ax,4c00h
int 21h
hi db 'HELLO'
end host
c: masm hello.asm
output of this says operand expected on line 1. Please tell me how to generate com files using this version of masm...
I know this is raising a long dead thread but I thought I'd chime in here as I could not find the answer to this online very easily.
Cannot be done with 5.1, however you can use EXE2BIN (just search on google) to convert it to a com file.
You can also use 6.11 which can be found at http://www.phatcode.net/downloads.php?id=175.
Once you have that running, your hello world app would be:
.MODEL TINY
.DOSSEG ; Make sure you are using dos segment CODE, DATA + STACK
.DATA
MSG DB "Hello, World!", 0Dh, 0Ah, '$'
.CODE
.STARTUP ; Setup the starting address otherwise you'll see:
; LINK : warning L4055: start address not equal to 0x100 for /TINY
MOV AH, 09h
MOV DX, OFFSET MSG
INT 21h
MOV AH, 4Ch
INT 21h
END
To compile: ML /AT HELLO.ASM (the /AT enables .MODEL TINY)
It should compile without warnings or errors tested on MASM 6.11 under MS-DOS 6.22 in DOSBOX.
Hope this helps someone who had the same issue as I.
It can be done in MASM 5.1 (or older). From the MASM 5.0 docs, here is the basic shell with your test program.
TITLE COMFILE
_TEXT SEGMENT
ASSUME CS:_TEXT,DS:_TEXT,ES:_TEXT,SS:_TEXT
ORG 100H
START:
mov ah,9
mov dx,offset hi
int 21h
mov ax,4c00h
int 21h
hi db 'HELLO','$'
_TEXT ENDS
END START
With the above file named COMFILE.ASM, assemble and convert to .com using the following steps:
A>MASM COMFILE;
Microsoft (R) Macro Assembler Version 5.00
Copyright (C) Microsoft Corp 1981-1985, 1987. All rights reserved.
51668 + 464828 Bytes symbol space free
0 Warning Errors
0 Severe Errors
A>LINK COMFILE;
Microsoft (R) Overlay Linker Version 3.60
Copyright (C) Microsoft Corp 1983-1987. All rights reserved.
LINK : warning L4021: no stack segment
A>EXE2BIN COMFILE.EXE COMFILE.COM
Which should produce:
A>DIR COMFILE.COM
Volume in drive A has no label
Directory of A:\
COMFILE COM 18 01-01-80 12:00p
1 File(s) 30208 bytes free
A>COMFILE.COM
HELLO
A little thread necromancy here, yes. I also wasn't able to find a clear, working example of this elsewhere so hopefully this will help someone in the future.
MASM 6.0 was the first version of MASM capable of using the tiny memory model and therefore the first version of MASM capable of producing COM files. It's not terribly difficult to find copies of MASM 6.11 around the internet, and MASM 6.11 is still capable of being used under pure DOS if necessary.
Source: http://support.microsoft.com/kb/24954

Debug Break on Win32 Api functions

I would like to have a break on the SetTimer function in order to see which components register what timers with what values. Is this possible?
Yes, you can do this. First make sure you have public symbols setup for your debugger.
SetTimer lives in user32 but that is just what it is exported as. The easiest way to do this is with the command line debugger, NTSD. We need its real name, so look for symbols in user32 that match:
0:000> x user32!*timer*
759992b9 USER32!NtUserValidateTimerCallback = <no type information>
759977d5 USER32!NtUserSetTimer = <no type information>
759e4f13 USER32!NtUserSetSystemTimer = <no type information>
759993bf USER32!NtUserKillTimer = <no type information>
Ah-ha! Its debug symbol is NtUserSetTimer:
0:000> bp user32!NtUserSetTimer
In Visual Studio, you can figure out where SetTimer lives by writting a simple scratch program and then setting a breakpoint and right clicking and selecting "Go to Disassembly":
int _tmain(int argc, _TCHAR* argv[]) {
SetTimer(NULL, 0, 0, NULL);
004113BE mov esi,esp
004113C0 push 0
004113C2 push 0
004113C4 push 0
004113C6 push 0
004113C8 call dword ptr [__imp__SetTimer#16 (418338h)]
If we step into that call, then we land here:
_NtUserSetTimer#16:
759977D5 mov eax,123Dh
759977DA mov edx,7FFE0300h
759977DF call dword ptr [edx]
759977E1 ret 10h
So the to set a breakpoint there in Visual Studio, you have to use the context operator in the breakpoint. Select from the menus: Debug -> New Breakpoint -> Break at Function, then enter:
{,,user32.dll}_NtUserSetTimer#16
Here's a walkthrough, with screenshots, for VS2005. Note that for VS2008+ you don't need to input decorated function names (perhaps that's the reason the previous description didn't work out directly? What's your platform/IDE ?).
[Edit:] You definitely need public MS symbols to be able to locate Win32 API in binaries. The shortest route there is go to Tools/Options/Debugging/Symbols, then paste 'http://msdl.microsoft.com/download/symbols' into 'pdb locations'. It is highly recommended - but not necessary - to set a local cache for downloaded pdb's (first pdb loads can be a few minutes), and for your needs you should probably uncheck 'Search the above locations only when symbols are loaded manually'. There'd be some startup delay as all symbols are loaded, but you won't have to chase down user32.dll (or whatever dll holds the function you wish to break at) and load its pdb manually.

Resources