I'm looking at some source code and don't understand what is going on. Here is some code I've put together from that source code (definitions came from all over the place and I've included only what's necessary):
#define TOC 0x1C75288
typedef unsigned int uint32_t;
typedef unsigned int uint;
struct opd_s
{
uint32_t Sub;
uint32_t Toc;
};
namespace Offsets{
enum Address{
GET_PLAYER_NAME = 0x421974
};
}
opd_s GET_PLAYER_NAME_t = { Offsets::GET_PLAYER_NAME, TOC };
char*(*GET_PLAYER_NAME)(uint PlayerID) = (char*(*)(uint))&GET_PLAYER_NAME_t;
Specifically, what do these last 2 lines mean and do? :
opd_s GET_PLAYER_NAME_t = { Offsets::GET_PLAYER_NAME, TOC };
char*(*GET_PLAYER_NAME)(uint PlayerID) = (char*(*)(uint))&GET_PLAYER_NAME_t;
Later in the source code I see a usage of GET_PLAYER_NAME and it looks like this:
char* player = GET_PLAYER_NAME(0);
So is GET_PLAYER_NAME some sort of a function that takes an argument of an integer?
I'm just really confused about this and am trying to understand it, so if someone could exaplain the meaning and syntax, that would be extremely helpful. Thanks!
opd_s GET_PLAYER_NAME_t = { Offsets::GET_PLAYER_NAME, TOC };
means create struct variable on stack with name GET_PLAYER_NAME_t of type opd_s and initialize it with fields Sub = Offsets::GET_PLAYER_NAME, i.e. 0x421974 and Toc = TOC, i.e. 0x1C75288.
So, there is a struct named GET_PLAYER_NAME_t with opd_s type, which is equal to { 0x421974, 0x1C75288 }.
char*(*GET_PLAYER_NAME)(uint PlayerID) = (char*(*)(uint))&GET_PLAYER_NAME_t;
It defines function pointer GET_PLAYER_NAME(uint PlayerID) which is pointed to former declared struct.
Actually GET_PLAYER_NAME(0) calls something with op-codes 0x421974, 0x1C75288, which we cannot know what it does, because we don't know the architecture it is compiled for (at least bitness and endianness of the architecture).
Surely it's not x86, DEP on x86 blocks executing stack data as code.
opd_s GET_PLAYER_NAME_t = { Offsets::GET_PLAYER_NAME, TOC };
This declares a variable named GET_PLAYER_NAME_t of type opd_s. This is initialized to { Offsets::GET_PLAYER_NAME, TOC } i.e. the Sub data member will be Offsets::GET_PLAYER_NAME and the Toc data member will be TOC.
char*(*GET_PLAYER_NAME)(uint PlayerID) = ...
This declares a variable named GET_PLAYER_NAME. Its type is: pointer to a function taking an uint as argument and returning `char *.
(char*(*)(uint))&GET_PLAYER_NAME_t;
This casts the adress of GET_PLAYER_NAME_t to a pointer ... see above.
This looks very suspicious as the contents of the GET_PLAYER_NAME_t variable which is a struct will be interpreted as the first instruction(s) in a function call via GET_PLAYER_NAME.
This is how functions are called on PS3 via a prx module. This code runs on an external plugin know as a prx module. Think of it kind of like a DLL. You can load the game's executable into IDA and get the address of the function you want to call. So in this case, 0x421974 is being called. Since we don't actually have the game's source, you need to define the function like this:
char*(*GET_PLAYER_NAME)(uint PlayerID) = (char*(*)(uint))&GET_PLAYER_NAME_t;
The opd structure is just an int array which is specific to the cell processor.
On Xbox it would just be like this:
char*(*GET_PLAYER_NAME)(uint PlayerID) = (char*(*)(uint))0x421974;
Pretty much all it does is call 0x421974 which is GET_PLAYER_NAME on GTA5 and gets a players name from their client index.
The processor is powerpc.
Related
I have been looking everywhere for this question, but I cannot seem to get the answer for this.
So, every example I have been to is simply how to grab function pointers from SO file, which I have done. However, let just say I have this compiled as my .SO file:
(these codes compiled into libsampleso.so):
sampleso.hpp:
#IFNDEF SAMPLESO_HPP__
#DEFINE SAMPLESO_HPP__
struct carDescriptor
{
const char* model;
int prod_year;
int wheel_num;
const char* license_plate;
const char* colour;
} car;
carDescriptor fillCarID(void);
#ENDIF
sampleso.cpp:
#include "sampleso.hpp"
//Struct car fillup function
carDescriptor fillCarID(void)
{
car.model = "Ford Fiesta";
car.prod_year = 2014;
car.wheel_num = 4;
car.colour = "Midnight Blue";
car.license_plate = "D 1234 ABC";
return car;
}
now, compiled, I've got these out of objdump -T libsampleso.so: car (the struct) and _Z9fillCarIDv (the function).
if the return value of _Z9fillCarIDv() (aka fillCarID()) is normal datatype (e.g. string or int), it's easy with dlsym. However, for this I need to cast the struct first and then the function. I've tried creating an empty struct, and then cast dlsym to it:
struct carDesc * cars;
cars = reinterpret_cast<struct carDesc*>(dlsym(hHandler,"car"));
but seems to be impossible to use that as the datatype for the function:
carDesc(*__fn_fillCarIDv)(void);
__fn_fillCarIDv = reinterpret_cast<carDesc(*)(void)>(dlsym(hHandler,"_Z9fillCarIDv"));
cars = __fn_fillCarIDv(); //doesn't work, error: function returns incomplete type "carDesc" C/C++(862)
Anyone ever tried to grab a struct using dlsym without .h file?
Also, how do you deal with the elements from the struct grabbed by dlsym? I know that you don't have the proper elements listed without .h file, and obviously some pointer shifting is necessary, but can anyone give me an example of how to do it?
Thanks
I have created a simple DLL in C++, for the sole purpose of isolating the issue and testing on a small scale the importing of a function that returns a list of structs with members of different types.
dll_header.h
#ifdef MY_DLL_EXPORTS
#define MY_DLL_API __declspec(dllexport)
#else
#define MY_DLL_API __declspec(dllimport)
#endif
enum color_type
{
RGB = 1,
MONO = 2
};
struct my_struct
{
unsigned char *name;
char *value;
color_type type;
my_struct* next;
};
extern "C" struct my_struct MY_DLL_API * get_list(void);
dll_header.cpp
#include "dll_header.h"
MY_DLL_API my_struct * get_list(void)
{
my_struct my_list[2];
unsigned char name1[] = "name1";
unsigned char name2[] = "name2";
char val1[] = "val1";
char val2[] = "val2";
my_list[0].name = name1;
my_list[0].value = val1;
my_list[0].type = RGB;
my_list[0].next = &my_list[1];
my_list[0].name = name2;
my_list[0].value = val2;
my_list[0].type = MONO;
my_list[0].next = NULL;
return my_list;
}
Like I said, I have to use these data types (cannot change them to strings or anything else because I am testing something and I need them like this)
Now, in my VB.NET application I import and try to retrieve the list like this from the DLL
Form1.vb
Imports System.Runtime.InteropServices
Imports System.Text
Public Class Form1
Public Enum color_type
RGB = 1
COLOR = 2
End Enum
Private Structure my_struct
Public name As Byte()
Public value As Char()
Public type As color_type
Public next As IntPtr
End Structure
Private Declare Function get_list Lib "my_lib.dll" () As IntPtr
Private my_list As List(Of my_struct)
Private Sub get_list()
Dim my_list_pointer As IntPtr = get_list()
my_list = New List(Of my_struct)
Dim my_item As my_struct
While my_list_pointer <> IntPtr.Zero
my_item = CType(Marshal.PtrToStructure(my_list_pointer, GetType(my_struct)), my_struct)
my_list.Add(my_item)
my_list_pointer = my_item.next
End While
End Sub
I have tried many other methods, specially changing data types but so far here I am, stuck with this exception when trying to run the code:
System.AccessViolationException: 'Attempted to read or write protected
memory. This is often an indication that other memory is corrupt.'
Trying to find a way to make these two understand each other
Either use mixed mode C++ to do the translation between native and managed types or use types that are compatible with P/Invoke.
Looking how Win32 define structure (and function that use those) is a good start to help you understand how to define compatible structures as one of the main intent of P/Invoke is to be able to use Win32 API from managed code.
If you go for mixed mode, then you can do whatever required translation between both world as you can mix native C++ and C++/CLI in the same assembly. So essentially, you would write code that convert the native structure into a managed one and then VB.NET will be able to use that managed code (assuming that you use types available in VB.NET for example).
Well, if you go for the mixed mode route, you generally ends up with 3 DLLs/Assemblies/Executable as you would have the original C++ DLL (native code), the VB.NET code (managed) and the mixed mode C++ assembly in between.
Update
While it could be relatively easy to provide code if the list is read only, if this is not the case, it could be much harder depending how the code is expected to be used and what are the availaible function in the existing DLL.
The starting point would be to create a ref class in C++/CLI.
Some similar questions
https://bytes.com/topic/c-sharp/answers/674468-passing-linked-list-c-dll-c-pinvoke
Return list of points (x,y,z) from C to C# using PInvoke
PInvoke of self referential struct from C++
Problem with your code
Your exported function retuns a pointer to a local variable which is undefined behavior.
Additional observation
If your original list is an array, the why making it a list also? An array would be easier to marshal and use. And probably perform better too.
When defining you structure, you have be explicit on how strings are marshalled and the alignment that should be used. You shoull validate that everything is as expected.
I'm having trouble defining a vector to be unbound when i use the Coder to generate C code. I wish to have a vector of type double 1x:inf, that will later generate a pointer to a struct containing the unbound vector when using Coder.
function [V2SAgent,bMove,s_Result] = V2SOnPublishedPrice(V2SAgent, oPPdata, ePochNow)
%#codegen
bMove = false;
s_Result = struct('d_BidMove', zeros(1,0),'d_AskMove', zeros(1,0),'i_VolBands', zeros(1,0));
coder.varsize('s_Result(:).d_BidMove',[1,inf],[false,true]));
coder.varsize('s_Result(:).d_AskMove',[1,inf],[false,true]));
coder.varsize('s_Result(:).i_VolBands',[1,inf],[false,true]));
coder.cstructname(s_Result, 'Move_t');
.....DOES ALOT OF WORK .....
When i process the function with the coder i end up with a struct looking like this.
struct emxArray_real_T_1x0
{
int size[2];
};
typedef struct {
emxArray_real_T_1x0 d_BidMove;
emxArray_real_T_1x0 d_AskMove;
emxArray_real_T_1x0 i_VolBands;
} Move_T;
The type emxArray_real_T_1x0 is by no means unbound. In other scenarios I managed to achieve the output I'm looking for using the Input, that I can define to be of time 1x:inf using the Coder, and using this to set the output variable in my function.
function s_Result = V2SOnPublishedPrice(infVector)
%#codegen
s_Result = struct('d_BidMove', zeros(1,0))
coder.varsize('s_Result(:).d_BidMove');
coder.varsize(d_BidMove);
coder.cstructname(s_Result, 'Move_t');
....SOME WORK....
s_Result.d_BidMove = infVector;
end
When put though to coder where infVector is defined as 1x:inf i get a output like this.
struct emxArray_real_T
{
double *data;
int *size;
int allocatedSize;
int numDimensions;
boolean_T canFreeData;
};
typedef struct {
emxArray_real_T *d_BidMove;
emxArray_real_T *d_AskMove;
emxArray_real_T *i_VolBands;
} Move_T;
For the scenario I used to define and test my functions this is fine, but I know I can't cover all the possible inputs I can get, so I need an output that is unbound so I have a uniform input/output across my functions, and I don't risk getting size mismatch or out of range errors.
I'm trying to add a socket filter to one of my sockets in C++ (Linux). In the socket filter I need to get the offset of struct fork_proc_event, which is nested within another structure. The definition looks like this (cn_proc.h):
struct proc_event {
...
union {
...
struct fork_proc_event {
__kernel_pid_t parent_pid;
...
} fork;
...
} event_data;
...
};
In C I would do this:
int off = offsetof(struct fork_proc_event, parent_pid);
However I'm developing in C++. If I try to do this:
int off = offsetof(proc_event::fork_proc_event, parent_pid);
I get the following error:
error: expected type-specifier
error: expected `,'
error: expected `)' before ',' token
How should the offsetof() line look like?
It may help to think of how an implementation of an offsetof macro might go. Here's one example:
#define offsetof(TYPE, MEMBER) \
((uintptr_t)&(((TYPE*)0)->MEMBER))
In other words, using 0 as a pointer to the type you're interested in, and simply taking the address of the struct field...
So if you wanted the offset of parent_pid relative to fork (which is how I initially parsed your question):
((char*)&((struct proc_event*)0)->event_data.fork.parent_pid) - ((char*)&((struct proc_event*)0)->event_data.fork)
On second reading it sounds like you might just want the offset of parent_pid relative to the start of struct proc_event. Adapting the example above that would be:
((uintptr_t)&((struct proc_event*)0)->event_data.fork.parent_pid)
I don't exactly understand the need for all those hacks, when all you have to do is give a name to your nested union type. Any name, just to be able to refer to it in C++ code
struct proc_event {
...
union whatever {
...
struct fork_proc_event {
__kernel_pid_t parent_pid;
...
} fork;
...
} event_data;
...
};
Then you'll be able to refer to it as proc_event::whatever::fork_proc_event in offsetof in C++ code
size_t off = offsetof(proc_event::whatever::fork_proc_event, parent_pid);
If you are interested in offset of parent_pid from the beginning of proc_event, you can do
size_t off = offsetof(proc_event, event_data.fork.parent_pid);
If you cannot change the declaration, you can calculate the offset of parent_pid inside fork_proc_event by doing
size_t off =
offsetof(proc_event, event_data.fork.parent_pid) -
offsetof(proc_event, event_data.fork);
(Although I can't say right away whether the last two are formally legal examples of offsetof usage, they will normally work in practice without any problems.)
I saw someone writing code like this , in a C++ class:
int foo ( int dummy )
{
this->dummy = dummy;
}
Shall we use code like that , will it cause problems ?
I tried to compile something like this , it seems to be worked.
#update:
I posted this mostly about the name dummy , and the internal variable this->dummy , and if it's problem causing
That's perfectly fine for a member function, other than you're missing a return statement. dummy will shadow the member variable and so you use this-> to refer to member.
int foo ( int dummy )
{
this->dummy = dummy; // set member to argument
return this->dummy;
}
Don't do this for things more complex than a simple set function, as it's confusing.
int foo ( int dummy ) // Bad practise! Rename this param as the function isn't a setter
{
this->dummy = dummy * 2 + 1;
return this->dummy;
}
There is nothing wrong with doing that perse. It can get confusing though if you use dummy assuming it is coming from the class but its actually coming from the parameter.
IMO, its better to use something to denote it is a class member. Some people use simply mDummy, other m_Dummy, others just write dummy_.
Its up to you what you prefer but most of all you should be consistent.
The code is not fine. The function is defined as returning an int but there is no return statement. The compiler might only give a warning about this, but the function calling foo might expect it to return a valid value, which it doesn't, and bad stuff might happen.
You have to do it this way if you're passing a parameter with the same name as the member variable.
But it might be a better practice to avoid a hidden (member-)variable by using different names. There's different coding styles, some would use dummy_, some would use mDummy or other ways to name member variables. This makes your code less confusing.
Well there is nothing wrong with your use, but the code needs to return an int as its an int function :)
Dummy variable in your current class is assigned to the passed int, however do remember they are different but now pointing to the same thing, therefore its better to give it a different name as its in a different.
You could however loose precision under certain variable types.
#include <stddef.h>
typedef struct intlist {
int size;
int i[1];
} intlist;
intlist *
makeintlist (int size)
{
intlist *ilp = malloc (offsetof (intlist, i[size])); /* not C++ */
ilp->size = size;
return ilp;
}
member variable size is allocated to size
That will work.
Don't do it, it's confusing!