I have a deep copy method in a custom container myCont. I have an instance of an unsorted container that I need to sort and dump. I create a temp container with sorted flag on, call the copy method and Dump. But the app code below creates an empty container and passes that rather than my (loaded) container. Need help figuring out what is going on here. Thanks in advance
void myCont::Copy(const myCont& srcCont)
{
// code to deep copy from srcCont
}
App Code:
fn(x, z, z) {
myCont dC();
dC.setSorted(true);
dC.Copy(sC);
dC.DumpCont();
}
Assembly:
myCont dC();
0000000140323068 mov dl,1
000000014032306A lea rcx,[dC]
0000000140323072 call myCont::myCont (0141E1A01Ah)
0000000140323077 nop
dSet.Copy(sC);
0000000140323078 cmp qword ptr [sC],0
0000000140323081 je CR::evaluate+6FDh (014032308Dh)
0000000140323083 mov byte ptr [rsp+0C2h],1
000000014032308B jmp CR::evaluate+705h (0140323095h)
000000014032308D mov byte ptr [rsp+0C2h],0
0000000140323095 movzx edx,byte ptr [rsp+0C2h]
000000014032309D lea rcx,[rsp+6F0h]
00000001403230A5 call myCont::myCont (0141E1A01Ah) <-WHY THIS CTROL CALL ????????????
00000001403230AA nop
00000001403230AB lea rdx,[rsp+6F0h]
00000001403230B3 lea rcx,[dC]
00000001403230BB call myCont::Copy (0141E1A188h)
00000001403230C0 nop
00000001403230C1 lea rcx,[rsp+6F0h]
00000001403230C9 call myCont::~my Cont(0140009280h)
dC.DumpCont();
00000001403230CE lea rcx,[dC]
00000001403230D6 call myCont::DumpCont(014019B240h)
This is not a complete example, but since you provided the assembly, I think I can tell what is going on.
sC is converting to a bool (cmp to zero, then set either a one or a zero). You must have an implicit constructor in the myCont class that can convert from a bool. sC is apparently not of type myCont. Is sC a myCont * by any chance?
From the little bit of code you posted:
void myCont::Copy(const myCont& srcCont)
{
// code to deep copy from srcCont
}
this indicates that myCont::Copy() doesn't return a new myCont object and it can't modify the srcCont object. So it's not clear what the Copy() function is actually supposed to be doing.
Also, myCont dC(); is an instance of the most vexing parse - it's a nop.
Related
TL;DR : Should we use fn(Interface* pMaybeNull) or fn(Interface& maybeNullObject) -- specifically in the case of "optional" function arguments of a virtual/abstract base class?
Our code base contains various forms of the following pattern:
struct CallbackBase {
virtual ~CallbackBase() = default;
virtual void Hello(/*omitted ...*/) = 0;
};
...
void DoTheThing(..., CallbackBase* pOpt) {
...
if (pOpt) { pOpt->Hello(...); }
}
where the usage site would look like:
... {
auto greet = ...;
...
DoTheThing(..., &greet);
// or if no callback is required from call site:
DoTheThing(..., nullptr);
}
It has been proposed that, going forward, we should use a form of the Null-Object-Pattern. like so:
struct NoopCall : public CallbackBase {
virtual void Hello(/*omitted ...*/) { /*noop*/ }
};
void DoTheThing2(..., CallbackBase& opt) {
...
opt.Hello(...);
}
... {
NoopCall noop;
// if no callback is required from call site:
DoTheThing2(..., noop);
}
Note: Search variations yield lots of results regarding Null-Object (many not in the C++ space), a lot of very basic treatment of pointer vs. references and if you include the word "optional", as-in the parameter is optional, you obviously get a lot of hits regarding std::optional which, afaik, is unsuitable for this virtual interface use case.
I couldn't find a decent comparison of the two variants present here, so here goes:
Given C++17/C++20 and a halfway modern compiler, is there any expected difference in the runtime characteristics of the two approaches? (this factor being just a corollary to the overall design choice.)
The "Null Object" approach certainly "seems" more modern and safer to me -- is there anything in favor of the pointer approach?
Note:
I think it is orthogonal to the question posed, whether it stands as posted, or uses a variant of overloading or default arguments.
That is, the question should be valid, regardless of:
//a
void DoTheThing(arg);
// vs b
void DoTheThing(arg=nullthing);
// vs c
void DoTheThing(arg); // overload1
void DoTheThing(); // overload0 (calling 1 internally)
Performance:
I inspected the code on godbolt and while MSVC shows "the obvious", the gcc output is interesting (see below).
// Gist for a MCVE.
"The obvious" is that the version with the Noop object contains an unconditional virtual call to Hello and the pointer version has an additional pointer test, eliding the call if the pointer is null.
So, if the function is "always" called with a valid callback, the pointer version is a pessimization, paying an additional null check.
If the function is "never" called with a valid callback, the NullObject version is a (worse) pessimization, paying a virtual call that does nothing.
However, the object version in the gcc code contains this:
WithObject(int, CallbackBase&):
...
mov rax, QWORD PTR [rsi]
...
mov rax, QWORD PTR [rax+16]
(!) cmp rax, OFFSET FLAT:NoopCaller::Hello(HelloData const&)
jne .L31
.L25:
...
.L31:
mov rdi, rsi
mov rsi, rsp
call rax
jmp .L25
And while my understanding of assembly is certainly near non existent, this looks like gcc is comparing the call pointer to the NoopCaller::Hello function, and eliding the call in this case!
Conclusion
In general, the pointer version should produce more optimal code on the micro-level. However, compiler optimizations might make any difference near non-observable.
Think about using the pointer version if you have a very hot path where the callback is null.
Use the null object version otherwise, as it is arguably safer and more maintainable.
In our VS2013 MFC Project, the CWinApp application class has a CWordArray member.
Looking at the dissassembly we can tell that the offset of this member is 21Eh.
This is the call to SetSize assembly code called from within the CwinApp:
m_arrayDefInd.SetSize(64, 1);
00F36D0F push 1
00F36D11 push 40h
00F36D13 mov ecx,dword ptr [this]
00F36D16 add ecx,21Eh <<<<<< NOTE OFFSET
00F36D1C call CWordArray::SetSize (0FC25E0h)
However, in a CView class, we retrieve the CwinApp pointer and reference this same member. When we look at the dissassembly code in the CView class, the compiler has set the offset at 230h.
CMyApp *pApp = (CMyApp *)AfxGetApp();
int size = pApp->m_arrayDefInd.GetSize();
00F2DA42 mov ecx,dword ptr [ebp-20h]
00F2DA45 add ecx,230h <<<<<< NOTE OFFSET
00F2DA4B call CWordArray::GetSize (0FC225Ch)
00F2DA50 mov dword ptr [ebp-24h],eax
We have done the obvious – clean, rebuild all. We have ensured both compilation units are using the same application header file.
The above was ported from a VS6 application that handles this correctly.
We're at a loss to explain the above. Can anyone help?
some quick info about me
I'm a MalwareResearcher since 2008 and C++/MASM Developer since 2013. Atm I improve and test my skills with malware samples and CrackMe's.
I found a really nice one and got stucked at the coding part :(
Code Snippet from crackme:
MOV EAX,004260AC ; ASCII "TUFMQ0hPLkRMTA=="
CALL 00407B10
JMP SHORT 004049FB
XOR EAX,EAX
MOV DWORD PTR SS:[LOCAL.1],-1
TEST EAX,EAX
JZ 00404AC3
MOV EAX,DWORD PTR DS:[EAX]
PUSH EAX ; /FileName
CALL DWORD PTR DS:[<&kernel32.LoadLibraryA>] ; \KERNEL32.LoadLibraryA
TEST EAX,EAX
JZ 00404AC3
PUSH 004260C0 ; /Procname = "Z2V0UGFzc3dvcmQ="
PUSH EAX ; |hModule
CALL DWORD PTR DS:[<&kernel32.GetProcAddress>] ; \KERNEL32.GetProcAddress
The crackme tries to load a dll called MALCHO.dll with LoadLibraryA and then tries to execute one its functions named Z2V0UGFzc3dvcmQ=.
After that it decrypts one of its resources with the password gathered from the dll's function Z2V0UGFzc3dvcmQ=.
As a part of the crackme it seems that I have to make this dll.
I was able to get the password which is needed for decryption by analysing another part of this specimen.
So "only" dll coding is needed to reach the end of the crackme :)
While decrypting TUFMQ0hPLkRMTA== to MALCHO.dll it seems that its function name Z2V0UGFzc3dvcmQ= is not decrypted to getPassword.
I don't now how to use a base64 encoded string as a function name in c++.
I get a syntax error in cause of the = in Z2V0UGFzc3dvcmQ= :(
My MALCHO.dll source:
MALCHO.h:
#ifdef MALCHODLL_EXPORTS
#define MALCHOFUNCSDLL_API __declspec(dllexport)
#else
#define MALCHOFUNCSDLL_API __declspec(dllimport)
#endif
namespace MALCHO
{
//This class is exported from the MalchoFuncsDll.dll
class MalchoFuncs
{
public:
// Returns password
static MALCHOFUNCSDLL_API char* Z2V0UGFzc3dvcmQ=(char* p);
};
}
MALCHO.cpp
#include "stdafx.h"
#include "MALCHO.h"
namespace MALCHO
{
char* MalchoFuncs::Z2V0UGFzc3dvcmQ=(char* p)
{
char* pw = "Yes I did it!";
return pw;
}
}
thanks in advance
MasDie
You can't use = as part of a name in C++, but GetProcAddress is an OS function which doesn't care about the language that you used. It just does string matching, and not very fancy either. It really cares only about \0 because that terminates the string. So, if you pass Z2V0UGFzc3dvcmQ=\0 it will look for an export named Z2V0UGFzc3dvcmQ=\0.
The syntax of a linker definition file for LINK.EXE won't allow you to add such a name, but again GetProcAddress doesn't care who put the name in the export table. The easiest solution is probably to add Z2V0UGFzc3dvcmQ_\0 and then overwrite the _
I have a function template parameterized by a template parameter T to give it different behavior depending on what T it is instantiated with. The specific variations desired are very simple, a call to a static function T::foo(some_args) would suffice, because no state is involved.
However I do not want to that foo to appear in the body of the function template.
I would rather call T(some_args);to avoid syntactic noise. I believe declaring the function call operator () to be static is not possible (or is it ?). T has no state, therefore no instance specific variables.
In the event the above is not possible, what has more chance of getting inlined / optimized (in G++, Clang, ICC)
T::foo(some_args); // foo being a static function
or
T()(some_args); // operator () declared inline
I dont know assembly to check the output, and the question is more from an academic/curiosity point of view than actual performance.
Does T()(some_args) really allocate an object at runtime ? or is it typically optimized away ?
Simple example:
struct T
{
int operator()(int i) const {
return i+1;
}
};
int main()
{
return T()(1);
}
Compiled with -O2 this will yield:
(gdb) disassemble main
Dump of assembler code for function main():
0x0000000000400400 <+0>: mov eax,0x2
0x0000000000400405 <+5>: ret
End of assembler dump.
Even with -O0 this will not create a temporary in case you use the implicit default constructor in T:
(gdb) disassemble main
Dump of assembler code for function main():
0x00000000004004ec <+0>: push rbp
0x00000000004004ed <+1>: mov rbp,rsp
0x00000000004004f0 <+4>: sub rsp,0x10
0x00000000004004f4 <+8>: lea rax,[rbp-0x1]
0x00000000004004f8 <+12>: mov esi,0x1
0x00000000004004fd <+17>: mov rdi,rax
0x0000000000400500 <+20>: call 0x400508 <T::operator()(int) const>
0x0000000000400505 <+25>: leave
0x0000000000400506 <+26>: ret
End of assembler dump.
I have a hack program; it injects some functions into a target process to control it. The program is written in C++ with inline assembly.
class GameProcMain {
// this just a class
};
GameProcMain* mainproc; // there is no problem I can do =(GameProcMain*)0xC1EA90
Now I want to define a class function (which set ecx to class pointer) instead of writing assembly.
PPLYDATA GetNearblyMob(__Vector3* cordinate) {
__asm {
mov ecx, 0xC1EA90
enter code here
push cordinate
mov edi, 0x4A8010
call edi
}
}
I want to define it and call it like.
PPLYDATA (DLPL::*GetNearblyMob)(__Vector3* cordinate);
mainproc->GetNearblyMob(ADDR_CHRB->kordinat)
When I try GetNearblyMob=(PPLYDATA (DLPL::*)(__Vector3*)) 0x4A8010;
It says something like error: invalid type conversion: "int" to "PPLYDATA (DLPL::*)(int, int)"
but I can do this to set the pointer:
void initializeHack() {
__asm {
LEA edi, GetNearblyMob
MOV eax, 0x4A8010
MOV [edi], eax
}
}
Now I want to learn "how I can set GetNearblyMob without using assembly and legitimately in C++".
The problem is that member functions automatically get an extra parameter for the this pointer. Sometimes you can cast between member and non-member functions, but I don't see the need to cast anything.
Typically it's easier to reverse-engineer into C functions than into C++. C typically has a more straightforward ABI, so you can keep the data structures straight as you work them out.
So, I would recommend
PPLYDATA (*GetNearblyMob)(DLPL *main_obj, __Vector3* cordinate) = 0x12345UL;
and then define your own function
class DLPL {
GetNearblyMob( __Vector3* cordinate ) {
return ::GetNearblyMob( this, cordinate );
}
// ... other program functions
};
I am a bit surprised that it won't you cast like that.
You can try to do something like
GetNearblyMob=reinterpret_cast<PPLYDATA (DLPL::*)(__Vector3*)> (0x4A8010);
If that still does not work, try
*(int*)(&GetNearblyMob) = 0x4A8010;