Inline __asm code for getting the address of TIB (fs:[0x18]) - winapi

I'd like to get the TIB of a process and afterwards get its PEB and so forth. I'm failing to do so because I'm having some issues with the __readfsdword(0x18) function, so I'd like to do it with __asm inline code, if possible.
The program is compiled for x86, so I think it means that the TIB will be located at offset 0x18 from the FS register. On x64 it should be on gs:[0x30].
How would I implement this inline assembly idea?
Edit
NtCurrentTeb() and __readfsdword gave different return addresses so I wanted to get as low-level as possible to figure out which one was malfunctioning.
The reason why __readfsdword wasn't working is because I think the libraries weren't compatible with each other, so I replaced them with the updated versions and now it's working properly.

__readfsdword/__readgsqword are compiler intrinsic functions that will generate more optimized code, there is no reason to use inline assembly. Inline assembly is not even supported by Microsoft's compilers for 64-bit targets.
#include <intrin.h>
__declspec(naked) void* __stdcall GetTEB()
{
__asm mov eax, dword ptr fs:[0x18] ;
__asm ret ;
}
...
void *teb;
__asm push eax ;
__asm mov eax, dword ptr fs:[0x18] ;
__asm mov teb, eax ;
__asm pop eax ;
printf("%p == %p == %p\n", GetTEB(), teb, __readfsdword(0x18));
And as suggested in the comments, NtCurrentTeb() is provided by the Windows SDK. It most likely just uses __readfsdword.

Related

How to get the EXCEPTION_POINTERS in Windows 32bit x86 assembly?

So I have some basic asm file that looks like the one below(print_eax is removed as it's large and unrelated to the question) and have been using this http://www.godevtool.com/ExceptFrame.htm as a source of information. But I'm unsure of how to get the EXCEPTION_POINTERS. I've tried popping from the stack, and using different registers in case it was passed through those, as well as various offsets from each of these, but honestly I'm at a loss and have been unable to find a solution through google. How do I get the EXCEPTION_POINTERS when we enter FINAL_HANDLER?
global _main
extern _GetStdHandle#4
extern _WriteFile#20
extern _ExitProcess#4
extern _SetUnhandledExceptionFilter#4
section .text
_main:
push FINAL_HANDLER
CALL _SetUnhandledExceptionFilter#4
;---Protected code---
mov eax, dword [0xffffffff] ;Force C0000005h exception
; ExitProcess(0)
push 0
call _ExitProcess#4
; never here
hlt
FINAL_HANDLER:
; get EXCEPTION_POINTERS
;????
; get EXCEPTION_RECORD(dword [EXCEPTION_POINTERS+0])
mov eax, dword [EXCEPTION_POINTERS]
; get ExceptionCode(dword [EXCEPTION_RECORD+0])
mov eax, dword [eax]
call print_eax ; a simple procedure that outputs eax in hex
; ExitProcess(1)
push 1
call _ExitProcess#4

How to enable inclusion of x86 and x64 asm files into a single Visual Studio project?

I'm using Visual Studio 2017 Community to build a test console C++ application. I need to include an assembly function into that project:
extern "C" void* __fastcall getBaseFS(void);
To include an asm file I right-clicked the project and went to "Build dependencies" -> "Build Customization" and checked "masm" in the list there.
I can then add an asm file by right-clicking my project -> Add New item -> and then add "asm_x64.asm" file where I write my x86-64 asm code:
.code
getBaseFS PROC
mov ecx, 0C0000100H ; IA32_FS_BASE
rdmsr
shl rdx, 32
or rax, rdx
ret
getBaseFS ENDP
END
This works in a 64-bit project.
The problem is that when I switch solution platform from x64 to x86:
my asm file needs to change. So in a sense I need to include a different "asm_x86.asm" file into compilation that is used only for x86 builds vs. x64 builds.
What's the best way to automate this switch?
OK, thanks to Michael Petch, I got it solved. Had to put both x64 and x86 code in one .asm file.
(There's another proposed option to deal with build configuration, but I prefer the method I'm showing here. I had a bad luck with those build configurations disappearing when solutions were moved from computer to computer.)
So, I'm not sure why using IFDEF RAX works, and Microsoft's own proposed ifndef X64 doesn't. But oh well. If anyone knows, please post a comment.
asm_code.asm file:
IFDEF RAX
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; x64 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; WinAPI to call
extrn Beep : proc
.data
align 8
beep_freq:
dq 700 ; hz
beep_dur:
dq 200 ; ms
str_from:
db "Hail from x64 asm", 0
.code
useless_sh_t_function__get_GS_a_string_and_beep PROC
; parameter = CHAR** for a string pointer
; return = value of GS register selector
mov rax, str_from
mov [rcx], rax
mov rdx, qword ptr [beep_dur]
mov rcx, qword ptr [beep_freq]
call Beep
mov rax, gs
ret
useless_sh_t_function__get_GS_a_string_and_beep ENDP
ELSE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; x86 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.686p
.XMM
.model flat, C
.data
align 4
beep_freq dd 700 ; hz
beep_dur dd 200 ; ms
str_from db "Hail from x86 asm", 0
.code
; WinAPI to call
extrn stdcall Beep#8 : proc
useless_sh_t_function__get_GS_a_string_and_beep PROC
; parameter = CHAR** for a string pointer
; return = value of GS register selector
mov eax, [esp + 4]
mov [eax], OFFSET str_from
push dword ptr [beep_dur]
push dword ptr [beep_freq]
call Beep#8
mov eax, gs
ret
useless_sh_t_function__get_GS_a_string_and_beep ENDP
ENDIF
END
main.cpp file:
#include "stdafx.h"
#include <Windows.h>
extern "C" {
size_t useless_sh_t_function__get_GS_a_string_and_beep(const CHAR** ppString);
};
int main()
{
const char* pString = NULL;
size_t nGS = useless_sh_t_function__get_GS_a_string_and_beep(&pString);
printf("gs=0x%Ix, %s\n", nGS, pString);
return 0;
}
Good that you found a way to handle your use case.
However, if you have more asm files, or only need them for some build types, you could also change the settings for each individual file for the parts where it differs from the project defaults.
Just right-click a file name to get to its individual properties.
To have an asm file included in x64 builds only, you can use these settings:
And then exclude it from 32-bit builds:
These settings are available for all file type, not only for .asm files.

VC++ Inline assembly errors

I have been searching around for a while, and couldn't seem to find the answer to my issue. I'm trying to code some functions to detect whether or not the executable is being debugged, and I'm using some inline assembly for it (with the __asm tag). It keeps throwing two errors, and the rest of the code seems to compile fine. Here's the function
int peb_detect() {
__asm {
ASSUME FS : NOTHING
MOV EAX, DWORD PTR FS : [18]
MOV EAX, DBYTE PTR DS : [EAX + 30]
MOVZX EAX, BYTE PTR DS : [EAX + 2]
RET
}
}
and I keep getting the errors
warning C4405: 'FS': identifier is reserved word
warning C2400: inline assembler syntax error in 'opcode'; found 'FS'
warning C2408: illegal type on PTR operator in 'second operand'
I can't seem to figure it out. If anyone can help, I would really appreciate it. Thanks!
at first not 18 but 0x18 and not 30 but 0x30
C_ASSERT(FIELD_OFFSET(NT_TIB, Self) == 0x18);
C_ASSERT(FIELD_OFFSET(TEB, ProcessEnvironmentBlock) == 0x30);
need use not hard coded constants. especially wrong.
at second int peb_detect() must be __declspec(naked) if you use RET instruction. so code can look like this:
#include <winternl.h>
#include <intrin.h>
__declspec(naked) BOOLEAN peb_detect() {
__asm {
MOV EAX, FS:[NT_TIB.Self]
MOV EAX, [EAX + TEB.ProcessEnvironmentBlock]
MOV AL, [EAX + PEB.BeingDebugged]
RET
}
}
but we can use and shorter variant
__declspec(naked) BOOLEAN peb_detect2() {
__asm {
MOV EAX, FS:[TEB.ProcessEnvironmentBlock]
MOV AL, [EAX]PEB.BeingDebugged
RET
}
}
and for implement IsDebuggerPresent we can not use inline assembler at all. and this will be work for x64 too
__forceinline BOOLEAN peb_detect3()
{
return ((PEB*)
#ifdef _WIN64
__readgsqword
#else
__readfsdword
#endif
(FIELD_OFFSET(_TEB, ProcessEnvironmentBlock)))->BeingDebugged;
}

C++Builder - implement entire function in assembly

I am trying to implement this inline assembly trick to obtain the value of EIP in C++Builder. The following code works in Release mode:
unsigned long get_eip()
{
asm { mov eax, [esp] }
}
however it doesn't work in Debug mode. In Debug mode the code has to be changed to this:
unsigned long get_eip()
{
asm { mov eax, [esp+4] }
}
By inspecting the generated assembly; the difference is that in Debug mode the code generated for the get_eip() function (first version) is:
push ebp
mov ebp,esp
mov eax,[esp]
pop ebp
ret
however in Release mode the code is:
mov eax,[esp]
ret
Of course I could use #ifdef NDEBUG to work around the problem ; however is there any syntax I can use to specify that the whole function is in assembly and the compiler should not insert the push ebp stuff? (or otherwise solve this problem).
Have you tried __declspec(naked)?
__declspec(naked) unsigned long get_eip()
{
asm { mov eax, [esp] }
}

save inline asm register value to C pointer, can get it on GCC but not VC

for the sake of simplicity ill just paste an example instead of my entire code which is a bit huge. while im porting my code to VC++ instead of using GCC i need to rewrite a few inline assembly functions that receive pointers and save values on those pointers.
imagine cpuid for example:
void cpuid( int* peax, int* pebx, int* pecx, int* pedx, int what ){
__asm__ __volatile__( "cpuid" : "=a" (*peax), "=b" (*pebx), "=c" (*pecx), "=d" (*pedx) : "a" (what) );
}
that will just work, it will save the values on the registers "returned" by cpuid on the pointers that i passed to the function.
can the same be done with the inline assembler for VC?
so far the exact same function signature but with:
mov eax, what;
cpuid;
mov dword ptr [peax], eax;
etc
wont work, peax will have the same value it had before calling the function.
thanks in advance.
Tough to see because it is just a snippet, plus it could be called from C++ code / thiscall.
It might have to be 'naked' ( __declspec(naked) ) in some cases.
It won't port as VC is dropping x64 inline asm support iirc.
Use the __cpuid or __cpuidex intrinsic and enjoy.
mov eax, what;
cpuid;
mov ecx, dword ptr peax;
mov [ecx], eax;
will work.
Good luck!

Resources