I trying to port the vaiven virtual machine code to windows for learning purposes.
I compiled and tested the code on Linux. Most of the c++ code compiles fine with visual studio 2019 community edition.
There is one function that i don't know how to port it to windows. My guess is that this class allows to get the base of the stack frame.
class Stack {
uint64_t* rbp();
};
uint64_t* __attribute__ ((noinline)) vaiven::Stack::rbp() {
asm("mov (%rbp), %rax");
}
After googling about assembler using Intel notations I deduced that the equivalent code would be:
__declspec(noinline) uint64_t* vaiven::Stack::rbp() {
__asm
{
mov rax, DWORD PTR [rbp];
}
}
But I don't have any background in assembler coding. So I have two questions :
Is this translation to intel assembler correct ?
The Visual Studio community edition does not support inline
assembler for x64 targets. But it supports Intrinsics . Can we get the base of the stack frame in C/C++ code without writing assembler code in an external file
?
Thanks
Related
If I use the _byteswap_uint64() intrinsic of MSVC with the mostly MSVC compatible compiler clang-cl the code generates a call to the external library function _byteswap_uint64() which does the well known mask and shift orgy. Whith MSVC I simply get a x86 BSWAP instruction which is there since the 486 so there shouldn't be any processor optimization level relevant here. clang-cl understands a lot of command line options MSVC doesn't understand, even -march=native. So if I have -march=native the code is still a call to the mentioned function.
I use clang-cl 13 through the IDE (installed from the Visual Studio installer).
Is there a way to get proper code like with MSVC ?
I've got it. Simply use the clang specific intrinsics with conditional compilation:
#include <cstdint>
#include <intrin.h>
uint64_t swapThis( uint64_t value )
{
#if defined(__llvm__)
return __builtin_bswap64( value );
#elif defined(_MSC_VER)
return _byteswap_uint64( value );
#endif
}
clang_ isn't defined with clang-cl under Windows but only with clang++ under Windows, so I had to use _llvm.
I am writing a simple rootkit (just to learn how the kernel works ;)) that is hooking the filldir function in the kernel.
I am using the inline hook method - writing a JMP opcode in the beginning of the function.
the function looks like -
struct sym_hook *sa;
unsigned char o_code[HIJACK_SIZE], n_code[HIJACK_SIZE];
unsigned long o_cr0;
// mov rax, $addr; jmp rax
memcpy(n_code, "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe0", HIJACK_SIZE);
*(unsigned long *)&n_code[2] = (unsigned long)new;
printk("Hooking function 0x%p with 0x%p\n", target, new);
memcpy(o_code, target, HIJACK_SIZE);
write_cr0(read_cr0() & (~ 0x10000));
memcpy(target, n_code, HIJACK_SIZE);
write_cr0(read_cr0() | 0x10000);
While compiling and testing on Ubuntu 16.04 (kernel 4.15) everything works just fine, but when using Ubuntu 19.10 (Kernel 5.3) - I get a crash every-time I insmod.
the crash is because of permissions when writing to protected memory - that means (I think so) that the write protection disabling line is not working (write_cr0(read_cr0() & (~ 0x10000));).
I didn't found any documentation explaining why it's not working on the new Kernel version, is it really a related to the kernel version? or I am doing something wrong ? My guess is that there was added some new protection method in the new version and the 'old' protection disabling is not working any more ...
also, if it's really kernel version issue, is there a way to disable that protection in the new kernel version?
btw, tried also disabling using this code -
unsigned long cr0 = read_cr0();
clear_bit(16, &cr0);
asm volatile("mov %0,%%cr0" : "+r"(cr0), "+m"(__force_order));
I want to call define a function in asm file and call this function from a Cpp file/function. Also I have to compile the project on 64-bit platform.
Please help me in doing that as I don't have much idea about assembly code. Any help will be appreciated.
Thanks
This file is an ASM file from ffdshow that performs some work with CPUID. It's both x64 and x86. YASM is used to assemble it.
What most people do today is not write ASM code but use intrinsic functions. There are intrinsic functions for all SSE/AVX/etc. even for low level ring0 instructions. Intrinsic functions allow the compiler to do extra optimizations and are shared between 32 and 64bit builds.
A code snippet would help, but if you want to place inline assembly within a regular C++ function, you can do that by placing it in an asm block like this:
void myClass::myFunc() {
// cpp code
int a = 0;
// ...
// asm code
__asm {
mov eax, ebx;
// ...
};
// more cpp code
// ...
}
I'm trying to port a program to x64 using vs2008. The problem is, however, that the is some inline asm code that is not supported on x64. This asm code is used to push arguments with unknown type or number to functions from dll. It is an interpeter based program in which you can specify a function to use from a certain dll and the program pushes the arguments and calles the function at compile time.
Using various sources I've concluded that generating seperate .asm files that contain asm functions which can be compiled unsing masm and their obj files linked to vs2008. Using different files for x86 and x64 the program builds for both problems. The problem is however, that the functions do not replicate what the inline asm is doing.
I converted the following inline code, for example:
double a = Evaluate(arg[i]).num;
_asm push a + 4
_asm push a
j += 8;
To:
double a = Evaluate(arg[i]).num;
EvaluateFuncArgFloat(a);
j += 8;
With the follwoing .asm file:
TITLE EvaluateFuncArgFloat (evaluate_asm.asm)
.386
.model flat, C
.code
EvaluateFuncArgFloat PROC a:DWORD
push a + 4
push a
ret
EvaluateFuncArgFloat ENDP
END
This does not do what I'm expecting. The double simply does not end up in the function as it did when using inline asm.
My guess is that there is a small error or something I've left out, but after many tries I can't seem to get it to work. Hopefully someone can help me with this problem, it is very much appriciated.
A sneaky way to do this could be
EvaluateFuncArgFloat PROC a:DWORD
pop eax ;ret address popped to a safe register (if not ax/eax)
push a + 4
push a
push eax ;ret address back at top of stack
ret
EvaluateFuncArgFloat ENDP
The problem is you've pushed 2 numbers onto the stack and not removed them a+4 and a
Presumably another part of your original code deals with this in the original program
I need to put markers to C++ code that should be visible in assembly or binary. It seems it’s straight forward to do it for 32 using inline assembly:
__asm {
NOP
NOP
NOP
}
or using DB assembly statement:
__asm {
DB 0x00, 0xFF, 0x10
}
But VisualStudio 2005 and better does not support inline assembly for x64. Is there any way to do it? Probably I can make a function in separate assembly module but how I can be sure that linker will put an actual assembly there instead of CALL?
Define a global volatile variable somewhere, say volatile __int64 blah = 0;. Then wherever you want some marker, use _InterlockedCompareExchange64(&blah, SOME_UNIQUE_CONSTANT1, SOME_UNIQUE_CONSTANT2);. You'll be guaranteed to find instructions loading ECX:EBX with SOME_UNIQUE_CONSTANT1 and EDX:EAX with SOME_UNIQUE_CONSTANT2 followed by LOCK CMPXCHG8B (0xF0, 0x0F, 0xC7, etc -- see instruction encoding details).
The MSDN says you can use intrinsic functions.
//MyAsmCode.asm
.code
MyFunction proc
...
MyFunction endp
end
compile it (ml64.exe).
You get object file (MS COFF 64): MyAsmCode.obj
In VS add MyAsmCode.obj to linker additional dep.
Now you can call this function. ;)