1

__dest = (byte *)(**(code **)(*plVar5 + 0x10))(plVar5,(ulonglong)(numBytes + 1)); memcpy(__dest,param_2,numBytes + 1);

Can someone please explain what the first line does step by step? I get that it's preparring a byte array for the memcpy function but I'm confused by the rest, especially that "code" type. Is that an opcode or something ?

2 Answers 2

4

code does mean that something is interpreted as code to execute (most likely a function)

But more can be recovered from this snippet than just that something is executed:

Step 1: (**(code **)(*plVar5 + 0x10))

This is most likely a C++ vtable call.

plVar5 should be some variable containing a C++ object, or rather a pointer that should be interpreted as a C++ object. At offset 0 (which is just written *plVar5) is the pointer to the vtable of the object. The element at offset 0x10 in the vtable is some function. If this is the 3rd (vtable[2]) or the 5th (vtable[4]) depends on the pointer size, but let's pretend this is 64bit for this explanation ). This means that this is the 3rd entry, which is typically the first true vtable function after the constructor and destructor at vtable[0] and vtable[1]. Lets call this function prepare_buffer.

So the more understandable translation would be

plVar5->vtable->prepare_buffer

Step 2: (byte *)plVar5->vtable->prepare_buffer(plVar5,(ulonglong)(numBytes + 1))

After substituting our previous result into (byte *)(**(code **)(*plVar5 + 0x10))(plVar5,(ulonglong)(numBytes + 1))

Because this is C++ function of an object the first parameter is the self parameter, which has to be present for non static functions. So the only true argument is (ulonglong)(numBytes + 1). The result is assigned to a variable of type byte * and casted as such.

Step 3: memcpy(__dest,param_2,numBytes + 1);

This is indeed just a memcopy to the buffer returned by the previous function. Because the only real argument of that previous function call was the number of bytes copied I am assuming it was setting up this buffer (and called it prepare_buffer). If you can find out the class of the variable plVar5 you can find the vtable for this class, and then find the actual function that is called here to confirm this.

Further Reading

If you want to learn more about this I suggest https://alschwalm.com/blog/static/2016/12/17/reversing-c-virtual-functions/ (which I skimmed to explain this) and looking at the Ghidra Advanced Course at https://ghidra.re/online-courses/ that includes a Chapter on "Virtual Function Tables" which covers the Ghidra specifics of getting proper decompiler output for such cases.

2
0

I'm fairly certain that:

(**(code **)(*plVar5 + 0x10))

Is a function pointer. So, the line looks more like:

__dest = (byte*) somefunction(plVar5,(ulonglong)(numBytes + 1));

The decompilation can sometimes get a bit hairy with all these casts and pointer arithmetic. If there is a lot of code using plVar5 plus some offset, you could likely, using context clues, define a custom datatype that makes it easier to read.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.