Pointer to struct with offset - c++

I have a pointer to struct, its 0xB7CD98. And the offset to some float value 0x540. How to get this value. All its in C++ and assembler. Another thing is that this its code from my dll injected to exe.
float buffer ;
_asm {
MOV EAX, [0xB7CD98]+0x540
MOV buffer, EAX
}
But it isn't work. Why?

Why are you using Assembly for that?
float* pBuffer = (float*)(0xB7CD98 + 0x540)
printf("%f", *pBuffer);

Disassembly of your code :
0FB310E7 mov eax,0B7D2D8h;
0FB310EC mov dword ptr [buffer],eax
//It just fill 'buffer' with 0xB7CD98+0x540
What you really want is this :
DWORD basePtr = *(DWORD*)0xB7CD98;
float someVal = *(float*)(basePtr + 0x540);
Or, if you wish to obtain a permanent pointer to this value :
typedef struct _XStruct
{
BYTE fill_0[0x540];
float Value;
}*PXStruct;
//...
PXStruct basePtr = (PXStruct)0xB7CD98;
//0F0745E7 mov dword ptr [basePtr],0B7CD98h
float buffer = basePtr->Value;
//0F0745EE mov eax,dword ptr [basePtr]
//0F0745F1 fld dword ptr [eax+540h]
//0F0745F7 fstp dword ptr [buffer]

Related

Storing register values from a hook in assembly/c++ and save to array

I'm trying to make a hook that takes the rdi from a function and stores it in an array.
I know how to do it using inline assembly as by the code example:
...
uintptr_t objStart = 0x0;
uintptr_t jmpBack = 0x0;
Ent* ents[255];
Ent* entsptr;
void hook()
{
__asm {
movss xmm10, [rdi + 0x54]
movss xmm11, [rdi + 0x58]
mov EntityObjStart, rdi
push rax
push rcx
push rdx
push rbx
push rsp
push rbp
push rsi
push rdi
}
__asm {
mov rax, ObjStart
mov[entsptr], rax
}
...
for (int i = 0; i < 254; i++)
{
if (ents[i] == 0)
{
ents[i] = entsptr;
break;
}
}
...
Sadly this won't work because MSVS doesn't support inline assembly for 64 bit. I tried doing a separate asm file and link that together with the project, which works, but I don't know how to pass in the pointers to the assembly file or get the RDI out so I can store it in the array...
If you guys have any suggestions, that would be amazing!

Will template function typedef specifier be properly inlined when creating each instance of template function?

Have made function that operates on several streams of data in same time, creates output result which is put to destination stream. It has been put huge amount of time to optimize performance of this function (openmp, intrinsics, and etc...). And it performs beautifully.
There is alot math involved here, needless to say very long function.
Now I want to implement in same function with math replacement code for each instance of this without writing each version of this function. Where I want to differentiate between different instances of this function using only #defines or inlined function (code has to be inlined in each version).
Went for templates, but templates allow only type specifiers, and realized that #defines can't be used here. Remaining solution would be inlined math functions, so simplified idea is to create header like this:
'alm_quasimodo.h':
#pragma once
typedef struct ALM_DATA
{
int l, t, r, b;
int scan;
BYTE* data;
} ALM_DATA;
typedef BYTE (*MATH_FX)(BYTE&, BYTE&);
// etc
inline BYTE math_a1(BYTE& A, BYTE& B){ return ((BYTE)((B > A) ? B:A)); }
inline BYTE math_a2(BYTE& A, BYTE& B){ return ((BYTE)(255 - ((long)((long)(255 - A) * (255 - B)) >> 8))); }
inline BYTE math_a3(BYTE& A, BYTE& B){ return ((BYTE)((B < 128)?(2*(((long)A>>1)+64))*((float)B/255):(255-(2*(255-(((long)A>>1)+64))*(float)(255-B)/255)))); }
// etc
template <typename MATH>
inline int const template_math_av (MATH math, ALM_DATA& a, ALM_DATA& b)
{
// ultra simplified version of very complex code
for (int y = a.t; y <= a.b; y++)
{
int yoffset = y * a.scan;
for (int x = a.l; x <= a.r; x++)
{
int xoffset = yoffset + x;
a.data[xoffset] = math(a.data[xoffset], b.data[xoffset]);
}
}
return 0;
}
ALM_API int math_caller(int condition, ALM_DATA& a, ALM_DATA& b);
and math_caller is defined in 'alm_quasimodo.cpp' as follows:
#include "stdafx.h"
#include "alm_quazimodo.h"
ALM_API int math_caller(int condition, ALM_DATA& a, ALM_DATA& b)
{
switch(condition)
{
case 1: return template_math_av<MATH_FX>(math_a1, a, b);
break;
case 2: return template_math_av<MATH_FX>(math_a2, a, b);
break;
case 3: return template_math_av<MATH_FX>(math_a3, a, b);
break;
// etc
}
return -1;
}
Main concern here is optimization, mainly in-lining of MATH function code, and not to break existing optimizations of original code. Without writing each instance of function for specific math operation, of course ;)
So does this template inlines properly all math functions?
And any suggestions how to optimize this function template?
If nothing, thanks for reading this lengthy question.
It all depends on your compiler, optimization level, and how and where are math_a1 to math_a3 functions defined.
Usually, the compiler can optimize this if the functions in question are inline function in the same compilation unit as the rest of the code.
If this doesn't happen for you, you may want to consider functors instead of functions.
Here are some simple examples I experimented with. You can do the same for your function, and check the behavior of different compilers.
For my example, GCC 7.3 and clang 6.0 are pretty good in optimizing-out function calls (provided they see the definition of the function of course). However, somewhat surprisingly, ICC 18.0.0 is only able to optimize-out functors and closures. Even inline functions give it some trouble.
Just to have some code here in case the link stops working in the future.
For the following code:
template <typename T, int size, typename Closure>
T accumulate(T (&array)[size], T init, Closure closure) {
for (int i = 0; i < size; ++i) {
init = closure(init, array[i]);
}
return init;
}
int sum(int x, int y) { return x + y; }
inline int sub_inline(int x, int y) { return x - y; }
struct mul_functor {
int operator ()(int x, int y) const { return x * y; }
};
extern int extern_operation(int x, int y);
int accumulate_function(int (&array)[5]) {
return accumulate(array, 0, sum);
}
int accumulate_inline(int (&array)[5]) {
return accumulate(array, 0, sub_inline);
}
int accumulate_functor(int (&array)[5]) {
return accumulate(array, 1, mul_functor());
}
int accumulate_closure(int (&array)[5]) {
return accumulate(array, 0, [](int x, int y) { return x | y; });
}
int accumulate_exetern(int (&array)[5]) {
return accumulate(array, 0, extern_operation);
}
GCC 7.3 (x86) produces the following assembly:
sum(int, int):
lea eax, [rdi+rsi]
ret
accumulate_function(int (&) [5]):
mov eax, DWORD PTR [rdi+4]
add eax, DWORD PTR [rdi]
add eax, DWORD PTR [rdi+8]
add eax, DWORD PTR [rdi+12]
add eax, DWORD PTR [rdi+16]
ret
accumulate_inline(int (&) [5]):
mov eax, DWORD PTR [rdi]
neg eax
sub eax, DWORD PTR [rdi+4]
sub eax, DWORD PTR [rdi+8]
sub eax, DWORD PTR [rdi+12]
sub eax, DWORD PTR [rdi+16]
ret
accumulate_functor(int (&) [5]):
mov eax, DWORD PTR [rdi]
imul eax, DWORD PTR [rdi+4]
imul eax, DWORD PTR [rdi+8]
imul eax, DWORD PTR [rdi+12]
imul eax, DWORD PTR [rdi+16]
ret
accumulate_closure(int (&) [5]):
mov eax, DWORD PTR [rdi+4]
or eax, DWORD PTR [rdi+8]
or eax, DWORD PTR [rdi+12]
or eax, DWORD PTR [rdi]
or eax, DWORD PTR [rdi+16]
ret
accumulate_exetern(int (&) [5]):
push rbp
push rbx
lea rbp, [rdi+20]
mov rbx, rdi
xor eax, eax
sub rsp, 8
.L8:
mov esi, DWORD PTR [rbx]
mov edi, eax
add rbx, 4
call extern_operation(int, int)
cmp rbx, rbp
jne .L8
add rsp, 8
pop rbx
pop rbp
ret

How to pass float as argument (inline-assembly)?

How to pass float as function argument (external call) and return float in inline assembly? An example below doesn't work and is crashing the app. The comments are mine, so they might be also wrong.
The first two lines are added by myself just for this example. Originally I start with two float values on st(0) and st(1) and there's nothing I can do about that.
fld a ; load float 'a' on st(0)
fld b ; load float 'b' on st(0), 'a' is now st(1)
sub esp, 4 ; make room for float
fstp dword ptr [esp] ; push st(0) on stack, pop st(0)
mov ecx, ebp ; move 'this' on ecx
call Class::ModValue ; returns float on st(0)
fcompp ; compare returned st(0) with st(1)
fnstsw ax
test ah, 41h
jnz Exit_label
The code snippet above is inside asm{} block, there is more unimportant code before and after that. The crash is happening between 1st line of this code fragment and ModValue function call.
Function signature:
float Class::ModValue(float value)
{
_LOG("ModValue") // doesn't show
return value;
}
Compiler: VisualStudio, Architecture: x86, Calling convention: __thiscall
if it's a __thiscall
According to msdn:
The __thiscall calling convention is used on member functions and is the default calling convention used by C++ member functions that do not use variable arguments. Under __thiscall, the callee cleans the stack, which is impossible for vararg functions. Arguments are pushed on the stack from right to left, with the this pointer being passed via register ECX, and not on the stack, on the x86 architecture.
source: https://msdn.microsoft.com/en-us/library/ek8tkfbw.aspx
then a small example:
float DoStuffs(void *pThis, float a)
{
float flResult = 0.0f;
__asm
{
push a;
mov ecx, pThis;
call Class::ModValue;
fstp[flResult];
}
return flResult;
}
Some extended example:
class Test
{
public:
float b;
float Add(float a);
};
float Test::Add(float a)
{
return a + this->b;
}
float CallTest(void* pThis, float x)
{
float flResult = 0.0f;
__asm
{
push x;
mov ecx, pThis;
call Test::Add;
fstp[flResult];
}
return flResult;
}
int main()
{
void* m = malloc(4);
*(float*)m = 2.0f;
std::cout << CallTest(m, 2.1f) << std::endl;
return 0;
}

Visual studio doesn't use EBP when referring to stack variable

I have the following C++ code
int myFuncSum( int a, int b)
{
int c;
c = a + b;
return c;
}
int main(int argc, char *argv[])
{
int result;
result = myFuncSum(100, 200);
return 0;
}
When I step through this in the disassembly window of Visual Studio 2008 on my Win7 Pro machine, I see the following for the call to myFuncSum():
int myFuncSum( int a, int b)
{
001C1000 push ebp
001C1001 mov ebp,esp
001C1003 push ecx
int c;
c = a + b;
001C1004 mov eax,dword ptr [a] <--------------------
001C1007 add eax,dword ptr [b] <--------------------
001C100A mov dword ptr [c],eax <--------------------
return c;
001C100D mov eax,dword ptr [c] <--------------------
}
As I have indicated, the four lines that refer to the variables a, b and c refer to them as such, not as offsets relative to EBP.
Can anyone please suggest what I need to do to Visual Studio to get it to refer to them via EBP? I have already disabled C++ optimisations in the project settings; without doing so I don't even get my function called.
The disassembler is just trying to be helpful, not spamming you too much about irrelevant details. Not entirely accidental, this syntax abbreviation is also permitted in inline assembly with the __asm keyword.
You can switch back-and-forth, right-click the disassembly window and untick Show Symbol Names. Now you'll see the real machine code:
c = a + b;
003613DE mov eax,dword ptr [ebp+8]
003613E1 add eax,dword ptr [ebp+0Ch]
003613E4 mov dword ptr [ebp-8],eax
return c;
003613E7 mov eax,dword ptr [ebp-8]

Replacing assembly instruction changes other instructions

I am trying to place a call instruction at a function to simulate a hook, so i should be replacing 6 bytes in the beginning of the function to place my call which is 2 bytes for the opcode and a dword for the address. however here is the disassembly of the function before i hook it
void realFunction()
{
00B533C0 push ebp
00B533C1 mov ebp,esp
00B533C3 sub esp,0C0h
00B533C9 push ebx
00B533CA push esi
00B533CB push edi
00B533CC lea edi,[ebp-0C0h]
00B533D2 mov ecx,30h
00B533D7 mov eax,0CCCCCCCCh
00B533DC rep stos dword ptr es:[edi]
MessageBox(NULL, "realFunction()", "Trace", MB_OK);
00B533DE mov esi,esp
00B533E0 push 0
00B533E2 push 0B56488h
00B533E7 push 0B56490h
00B533EC push 0
00B533EE call dword ptr ds:[0B5613Ch]
00B533F4 cmp esi,esp
00B533F6 call _RTC_CheckEsp (0B53A10h)
}
and strangely here is it after i just replace 6 bytes
void realFunction()
{
00B533C0 call fakeFunction (0B52EF0h)
00B533C5 rol byte ptr [eax],0 <--
00B533C8 add byte ptr [ebx+56h],dl <--
00B533CB push edi <--
00B533CC lea edi,[ebp-0C0h] <--
00B533D2 mov ecx,30h
00B533D7 mov eax,0CCCCCCCCh
00B533DC rep stos dword ptr es:[edi]
MessageBox(NULL, "realFunction()", "Trace", MB_OK);
00B533DE mov esi,esp
00B533E0 push 0
00B533E2 push 0B56488h
00B533E7 push 0B56490h
00B533EC push 0
00B533EE call dword ptr ds:[0B5613Ch]
00B533F4 cmp esi,esp
00B533F6 call _RTC_CheckEsp (0B53A10h)
}
code for the hook
#include <iostream>
#include <windows.h>
using namespace std;
void realFunction()
{
MessageBox(NULL, "realFunction()", "Trace", MB_OK);
}
__declspec(naked) void fakeFunction()
{
__asm {
pushad;
pushfd;
}
MessageBox(NULL, "fakeFunction()", "Trace", MB_OK);
__asm{
popfd;
popad;
ret; //This should return back and resumes the execution of the original function;
}
}
void main()
{
DWORD size = sizeof(double);
DWORD oldProtection;
DWORD realFunctionAddr = (DWORD)realFunction;
DWORD fakeFunctionAddr = (DWORD)fakeFunction;
VirtualProtect((LPVOID)realFunctionAddr, size, PAGE_EXECUTE_READWRITE, &oldProtection);
*((PBYTE)(realFunctionAddr)) = 0xE8;
*((PDWORD)(realFunctionAddr + 1)) = fakeFunctionAddr - realFunctionAddr - 5;
VirtualProtect((LPVOID)fakeFunctionAddr, size, oldProtection, &oldProtection);
realFunction();
while (true){
cin.get();
}
}
I want to understand why this happens, why not just the 6 bytes i replaced are changed ?
As you can see, the sub esp,0C0h instruction begins at address 00B533C3, but the next instruction push ebx begins at address 00B533C9. You have overwritten addresses 00B533C0 through 00B533C5, so immediately after your 6 bytes you are in the middle of the sub esp,0C0h instruction.
The disassembler has no way of knowing that a certain byte is garbage and not an instruction, so it tries to interpret the bytes as instructions, as best as it can, and what you see is, of course, nonsensical instructions. After a while it just so happens (by coincidence) that the end of a nonsensical instruction coincides with the end of an actual instruction that used to be there, so from that point on the disassembler interprets instructions successfully, that's why the remainder of your function looks okay.
If you look at the actual bytes, and not at the assembly language mnemonic interpretations of these bytes, you will see that nothing funky is going on.
(Except, perhaps, for the fact that you appear to have replaced 5, not 6 bytes.)