C++ - Method/Member access - c++

We all know that private methods and members are only accessable inside the class, same way that protected methods and members are accessable inside the class and classes that derived from that class. But where is the «access control» of this? Does the «access control» happen in compile time, or does the compiler add addional machine code that controls that in runtime?
Can I create a class like this:
class Print
{
public:
void printPublic();
private:
void printPrivate();
};
int main()
{
Print print;
print.printPublic() // Change this to printPrivate() after compiling the code
return(EXIT_SUCCESS);
}
And then after compiling the code edit the machine code to call printPrivate() instead of printPublic() method without error?

Once you've fiddled around with the machine code, you're no longer compiling C++, but you're programming directly in machine code.
Your question is therefore somewhat moot.
You can regard the access specifiers as being essentially compile time directives, but note that the compiler can make optimisation choices based on them. In other words, it could be either. The C++ standard doesn't have to say anything about this either.

The «access control» happen at compile time and only for c++ code. you even not need edit the machine code - you can easy call private methods from assembly language - so this demonstrate that this is only for c++ restriction. and of course no any additional machine code that controls that in run-time - this at all impossible control who call method.
simply demo . note function names, how it mangled depended from x86 or x64 compiling and from compiler probably - my demo for CL compiler and x64 platform bat it can be easy changed to x86 or other compiler
c++ code
class Print
{
public:
void printPublic();
private:
void printPrivate();
};
// must be not inline or referenced from c++ code or will be droped by compiler!
void Print::printPrivate()// thiscall
{
DbgPrint("%s<%p>\n", __FUNCTION__, this);
}
void Print::printPublic()// thiscall
{
DbgPrint("%s<%p>\n", __FUNCTION__, this);
}
extern "C"
{
// stub impemeted in asm
void __fastcall Print_printPrivate(Print* This);
void __fastcall Print_printPublic(Print* This);
};
Print p;
//p.printPrivate();//error C2248
p.printPublic();
Print_printPrivate(&p);
Print_printPublic(&p);
and asm code (for ml64)
_TEXT segment 'CODE'
extern ?printPrivate#Print##AEAAXXZ:proc
extern ?printPublic#Print##QEAAXXZ:proc
Print_printPrivate proc
jmp ?printPrivate#Print##AEAAXXZ
Print_printPrivate endp
Print_printPublic proc
jmp ?printPublic#Print##QEAAXXZ
Print_printPublic endp
_TEXT ENDS
END
also note for x86 only that all c++ methods use thiscall calling convention - first parameter this in ECX register and next in stack as for __stdcall - so if method have no parameters (really one this ) we can use __fastcall for asm function as is, and if exist parameters we need push EDX to stack in assembler stub. for x64 no this problem - here only one calling convention, but all this already not related to main question.
example for x86 code with extra params, for show how transform __fastcall to __thiscall
class Print
{
public:
void printPublic(int a, int b)// thiscall
{
DbgPrint("%s<%p>(%x, %x)\n", __FUNCTION__, this, a, b);
}
private:
void printPrivate(int a, int b);
};
// must be not inline or referenced from c++ code or will be droped by compiler!
void Print::printPrivate(int a, int b)// thiscall
{
DbgPrint("%s<%p>(%x, %x)\n", __FUNCTION__, this, a, b);
}
extern "C"
{
// stub impemeted in asm
void __fastcall Print_printPrivate(Print* This, int a, int b);
void __fastcall Print_printPublic(Print* This, int a, int b);
};
Print p;
//p.printPrivate(1,2);//error C2248
p.printPublic(1, 2);
Print_printPrivate(&p, 1, 2);
Print_printPublic(&p, 1, 2);
and asm
.686p
_TEXT segment
extern ?printPublic#Print##QAEXHH#Z:proc
extern ?printPrivate#Print##AAEXHH#Z:proc
#Print_printPrivate#12 proc
xchg [esp],edx
push edx
jmp ?printPrivate#Print##AAEXHH#Z
#Print_printPrivate#12 endp
#Print_printPublic#12 proc
xchg [esp],edx
push edx
jmp ?printPublic#Print##QAEXHH#Z
#Print_printPublic#12 endp
_TEXT ends
end

The «access control» happen at compile time

Related

make compiler copy function's code inside a other function passed as argument

My question is very specific, i want force compiler to take the code of a funtion and copy it inside a another one, like inline or __forceinline keywords can do, but i want pass the function i want to copy in the other funtion, as an argument. Here is a simple example.
using pFunc = void(*)();
void func_1() { /*some code*/ }
void func_2(pFunc function) { /*some code*/ } //after compile i want this funtion takes no argument and copy the func_1 inside this.
int main()
{
func_2(func_1);
}
so with this example the compiler will pass the pointer of func_1 as argunent to func_2, as expected.
I tried add inline keyword for func_1 and also tried to pass the argument of func_2 as reference, but compiler didn't copied the func_1 inside func_2.
Any idea how can i do that?
I use the compiler of visual studio(msvc) with toolset 2017(v141).
My project platform is x64.
You can use a noinline template function to get the asm you want
So you want the compiler to do constant-propagation into a clone of void func_2(pFunc f){ f(); }? Like what GCC might do with __attribute__((noinline)) but not noclone?
For example,
using pFunc = void(*)();
int sink, sink2;
#ifdef _MSC_VER
#define NOINLINE _declspec(noinline)
#else
#define NOINLINE __attribute__((noinline)) // noclone and/or noipa
#endif
__attribute__((always_inline)) // without this, gcc chooses to clone .constprop.0 with just a jmp func_2
void func_1() { sink = 1; sink2 = 2; }
NOINLINE static void func_2(pFunc function) { function(); }
int main()
{
func_2(func_1);
}
produces, with GCC11.3 -O2 or higher, or -O1 -fipa-cp, on Godbolt. (Clang is similar):
# GCC11 -O3 with C++ name demangling
func_1():
mov DWORD PTR sink[rip], 1
mov DWORD PTR sink2[rip], 2
ret
func_2(void (*)()) [clone .constprop.0]:
mov DWORD PTR sink[rip], 1
mov DWORD PTR sink2[rip], 2
ret
main:
# note no arg passed, calling a special version of the function
# specialized for function = func_1
call func_2(void (*)()) [clone .constprop.0]
xor eax, eax
ret
Of course if we hadn't disabled inlining of func_2, main would just call func_1. Or inline that body of func_1 into main and not do any calls.
MSVC might not be willing to do that "optimization", instead preferring to just inline func_2 into main as call func_1.
If you want to force it to make clunky asm that duplicates func_1 unnecessarily, you could use a template to do the same thing as constprop, taking the function pointer as a template arg, so you can instantiate func_2<func1> as a stand-alone non-inline function if you really want. (Perhaps with _declspec(noinline)).
Your func_2 can accept func_1 as an unused argument if you want.
using pFunc = void(*)();
int sink, sink2;
#ifdef _MSC_VER
#define NOINLINE _declspec(noinline)
#define ALWAYS_INLINE /* */
#else
#define NOINLINE __attribute__((noinline)) // not noclone or noipa, we *want* those to happen
#define ALWAYS_INLINE __attribute__((always_inline))
#endif
//ALWAYS_INLINE // Seems not needed for this case, with the template version
void func_1() { sink = 1; sink2 = 2; }
template <pFunc f>
NOINLINE void func_2() { f(); }
int main()
{
func_2<func_1>();
}
Compiles as desired with MSVC -O2 (Godbolt), and GCC/clang
int sink DD 01H DUP (?) ; sink
int sink2 DD 01H DUP (?) ; sink2
void func_2<&void func_1(void)>(void) PROC ; func_2<&func_1>, COMDAT
mov DWORD PTR int sink, 1 ; sink
mov DWORD PTR int sink2, 2 ; sink2
ret 0
void func_2<&void func_1(void)>(void) ENDP ; func_2<&func_1>
void func_1(void) PROC ; func_1, COMDAT
mov DWORD PTR int sink, 1 ; sink
mov DWORD PTR int sink2, 2 ; sink2
ret 0
void func_1(void) ENDP ; func_1
main PROC ; COMDAT
$LN4:
sub rsp, 40 ; 00000028H
call void func_2<&void func_1(void)>(void) ; func_2<&func_1>
xor eax, eax
add rsp, 40 ; 00000028H
ret 0
main ENDP
Note the duplicated bodies of func_1 and func_2.
You should check (with a disassembler) that the linker doesn't do identical code folding and just attach the both symbol names to one block of machine code.
I don't think this looks like much of an obfuscation technique; IDK why having a 2nd copy of a function with identical machine code would be a problem to reverse engineer. I guess it would maybe create more overall work, and people wouldn't notice that two calls to different functions are actually doing the same thing.
I mostly answered as an exercise in making a compiler spit out the asm I wanted it to, whether or not that has value to anyone else.
Obviously it only works for compile-time-constant function pointers; commenters have been discussing self-modifying code and scripting languages. If you wanted this for non-const function pointer args to func_1, you're completely out of luck in a language like C++ that's designed for strictly ahead-of-time compilation.

Best way to declare member functions in a hpp file that point to an existing memory address

Due to changes in the MVSC x86/x64 compiler, I cannot use __asm(jmp addr) to perform direct functions via the memory address in the project.
For non-member functions, this Q&A did the trick: replace inline assembly tailcall function epilogue with Intrinsics for x86/x64 msvc
But for member functions, I now need an alternative; it must be pointed out that this is also required for constructors and deconstructors, as well as for functions of the same name for which my variant does not work. Of course, suggestions for improvement are also welcome, and yes, I only have the memory address, so there is no other way to call it up.
zstring.hpp:
#pragma once
#include <string>
#include "../asmjmp.h"
int __cdecl operator==(class zSTRING const &, char const * const);
int __cdecl operator==(class zSTRING const &, class zSTRING const &);
class zSTRING
{
public:
zSTRING() {
__asm( jmp 0x00402AF0);
}
zSTRING(zSTRING const &) {
__asm( jmp 0x00416500);
}
~zSTRING() {
__asm( jmp 0x00401160);
}
int Overwrite(unsigned int, class zSTRING const &) {
__asm( jmp 0x0046B6A0);
}
int Overwrite(string) {
__asm( jmp 0x0046B6FF);
}
int Insert(unsigned int, class zSTRING const &) {
__asm( jmp 0x0046B400);
}
/* My Variant: */
int (*Insert)(unsigned int, class zSTRING const &) = ((int(*)(unsigned int, class zSTRING const &))0x0046B400);
int Delete(class zSTRING const &, enum zTSTR_KIND) {
__asm( jmp 0x0046BCF0);
}
/* My Variant: */
int (*Delete)(class zSTRING const &, enum zTSTR_KIND) = ((int(*)(class zSTRING const &, enum zTSTR_KIND))0x0046BCF0);
char * ToChar() const
{
__asm( jmp 0x004639D0);
}
zSTRING Copied(unsigned int, unsigned long) const
{
__asm( jmp 0x0046C170);
}
zSTRING &operator+=(char const *) {
__asm( jmp 0x0067A7B0);
}
/* My Variant (without knowing if it would work): */
zSTRING (*&operator+=)(char const *) = ((zSTRING (*)(char const *))0x0067A7B0);
char & operator[](unsigned int) {
__asm( jmp 0x00445A20);
}
/* My Variant (without knowing if it would work): */
char & (operator[])(unsigned int) = ((char &(*)(unsigned int))0x00445A20);
};
if you want that some function containing single jmp instruction to some address - you need declare it with __declspec(dllimport) (this is Microsoft Specific and work only for CL compiler but think another compilers have equvalent syntax). say for example
void __declspec(dllimport) TrimLeft(char);
in case you ned this for all member functions in class - declare all class with this:
class __declspec(dllimport) zSTRING
{
zSTRING();
// .. more declarations
};
this will have effect on all not virtual member functions and static data member for class like it declared with __declspec(dllimport)
when function declared with __declspec(dllimport) compiler declared extern pointer variable:
extern void* __imp___FUNCDNAME__;
where __FUNCDNAME__ is decorated name of function + __imp_ prefix; and every time when you call such function compiler generate call __imp___FUNCDNAME__ instruction (after pass function arguments to registers or stack). with Edit and Continue options compiler usually generate less optimized code:
call func
func:
jmp __imp___FUNCDNAME__ ; exactly what you try - single jmp in function body
which is by fact equivalent to single call __imp___FUNCDNAME__
now obvious that for every imported functions void* __imp___FUNCDNAME__ must be somewhere defined and containing real function address. otherwise you got well known linker error LNK2001: unresolved external symbol
usually we use LIB file where exactly defined __imp___FUNCDNAME__ symbols - in this case linker put all this __imp_* variable in IAT section of PE and describe it in import section. as result loader assign correct address for every __imp___FUNCDNAME__ when load your image.
if you try import this functions from some DLL and this DLL export this functions - you must have LIB file for this. even if you have no LIB - you can easy create you yourself - create separate project with output file name exactly match to dll name from which you will call code and "implement" all this functions with __declspec(dllexport) for every single function or class. implementation of every function - can be empty or single return 0; - really when we build lib - it not containing any code (as result implementation can be fake/empty). it containing exactly function names and dll name (because this output file name for project must be exactly dll name. but say project target - exe or dll - does not matter). in general - this must look like:
void __declspec(dllexport) TrimLeft(char)
{
}
class __declspec(dllexport) zSTRING
{
public:
zSTRING()
{
}
int Overwrite(unsigned int, class zSTRING const &)
{
return 0;
}
//...
};
you easy build this code and got LIB file (import library) all what you need.
in case this functions not exported - unclear from where you got addresses, but in any case - this can not be hard-coded absolute addresses. you can in extreme case use hard-coded RVA from DLL... in any case if this functions not exported - you need yourself define all __imp___FUNCDNAME__ yourself. and yourself assign correct function addresses for it at begin.
because __FUNCDNAME__ usually containing illegal for C/C++ symbols - you will be need declare it in asm, something like:
_BSS segment
__imp_?TrimLeft##YAXD#Z DQ ?
__imp_??0zSTRING##QEAA#XZ DQ ?
__imp_??1zSTRING##QEAA#XZ DQ ?
__imp_??0zSTRING##QEAA#AEBV0##Z DQ ?
__imp_?Insert#zSTRING##QEAAHIAEBV1##Z DQ ?
public __imp_?TrimLeft##YAXD#Z
public __imp_??0zSTRING##QEAA#XZ
public __imp_??1zSTRING##QEAA#XZ
public __imp_??0zSTRING##QEAA#AEBV0##Z
public __imp_?Insert#zSTRING##QEAAHIAEBV1##Z
_BSS ends
and implement function for resolve import yourself
resolveimport proc
lea rax,[rcx + rva_1]
mov __imp_?TrimLeft##YAXD#Z,rax
lea rax,[rcx + rva_2]
mov __imp_??0zSTRING##QEAA#XZ,rax
;...
ret
resolveimport endp
say you call resolveimport from c++ code with address of dll - resolveimport(LoadLibraryW(L"my.dll"));

__cdecl, __stdcall and __fastcall are all called the exact same way?

I am using Visual C++ 2010, and MASM as my x64-Assembler.
This is my C++ code:
// include directive
#include "stdafx.h"
// functions
extern "C" int Asm();
extern "C" int (convention) sum(int x, int y) { return x + y; }
// main function
int main()
{
// print asm
printf("Asm returned %d.\n", Asm());
// get char, return
_getch();
return EXIT_SUCCESS;
}
And my assembly code:
; external functions
extern sum : proc
; code segment
.code
Asm proc
; create shadow space
sub rsp, 20o
; setup parameters
mov ecx, 10
mov edx, 15
; call
call sum
; clean-up shadow space
add rsp, 20o
; return
ret
Asm endp
end
The reason I am doing this is so I can learn the different calling conventions.
I would make sum's calling convention stdcall, and modify the asm code so it would call sum the "stdcall" way. Once I got that working, I would make it, say, fastcall, and then call it in asm the "fastcall" way.
But look at my assembly code right now. When I use that code, no matter if sum is stdcall, fastcall or cdecl, it will compile, execute fine, and print 25 as my sum.
My question: How, and why can __cdecl, __stdcall and __fastcall all be called the exact same way?
The problem is that you're compiling for x64 targets. From MSDN
Given the expanded register set, x64 just uses the __fastcall calling
convention and a RISC-based exception-handling model. The __fastcall
model uses registers for the first four arguments and the stack frame
to pass the other parameters.
Switch over to compiling for x86 targets, and you should be able to see the various calling conventions in action.
As far as i know x64 only uses the __fastcall convention. __cdecl and stdcall will just be compiled as __fastcall.

Call function from shared library in GCC with inline assembler

I've created shared library (will be used like plugin). There are a lot of functions like a
extern "C" long __attribute__ ((__cdecl__)) SumAgrs(long X, long Y, long Z, long *Out)
{
*Out = X + Y + Z;
return 0;
}
I would like to call functions from this library in C++(GCC, Linux), but not in compile time. When I use inline assembler, the "push" instruction corrupt local variables, and i have no idea how to fix it.
typedef int (*FARPROC)();
void *dl_handle = dlopen("plugin.so", RTLD_LAZY);
FARPROC proc = (FARPROC)dlsym(dl_handle, "SumAgrs");
long result;
asm("leal %0, %%eax\n\r" \
"pushl %%eax" : : "m" (result));
asm("pushl $10");
asm("pushl $15");
asm("pushl $20");
asm("call *%0" : : "m" (proc));
Result binary file contains something like call *24(%esp). So my pushl change %esp and call cause segmentation fault. But how to avoid this behavior?
thx
Look at libffi: "A Portable Foreign Function Interface Library"
"The libffi library provides a portable, high level programming interface to various calling conventions. This allows a programmer to call any function specified by a call interface description at run-time."
http://sourceware.org/libffi/
You needn't assembler to call functions, actually:
extern "C"
{
typedef long __attribute__ ((__cdecl__)) (*Proc)(long X, long Y, long Z, long *Out);
}
void *dl_handle = dlopen("plugin.so", RTLD_LAZY);
Proc proc = (Proc)dlsym(dl_handle, "SumAgrs");
proc(...); // call
Note, that either you call functions with c-code, or with ASM inline, your code for call generated in compile time. You cannot pass string variable to asm, because code for your asm inline should be generated during program compilation. That means you cannot do
std::string asm_code;
std:: cin >> asm_code;
asm(asm_code);

linking assembly and c problem

Trying to understand how to link a function that is defined in a struct, the function is in the assembly code, and am trying to call it from c. I think am missing a step cause when I call the function, I get an unresolved external symbol...
;Assembly.asm
.686p
.mmx
.xmm
.model flat
include Definitions.inc
.code
?Initialize#Foo##SIXPAUFee###Z proc
jmp $
?Initialize#Foo##SIXPAUFee###Z endp
end
//CFile.c
struct Fee
{
signed long id;
}
struct Foo
{
static void Initialize(Fee *);
}
int startup(Fee * init)
{
Foo::Initialize(init); //<-- This is unresolved
return 0;
}
Your assembly code defines a function whose decorated name decodes to
public: static void __fastcall Foo::InitializeCurrentCpu(struct Fee *)
As obtained through the undname.exe utility. Foo::InitializeCurrentCpu() won't be a match for Foo::Initialize(), the name doesn't match. Nor does the calling convention.
Write this code in C++ first and look at the .map file for the correct decorated name. Or declare the function with extern "C" to suppress C++ decoration.