1

For the bit of background, I'm a robotic engineer. Robotics manufactures hide some parameters of their robots in order to avoid their competition. Now, I need these data to compute the dynamics model of the robot. I'm working on establishing an ideal "pathfinder" in term of energy consumption.

Basically, I have a .dat file gathering all the parameters I want, but I don't know "which one" is "which one".

I've copied the code from the robot and dissasembled it using Ida pro. Now, I have some pseudo code that I analyse.

  FILE *__cdecl CDynamicData::loadRobcorFile(CDynamicData *this, char 

*filename, unsigned __int16 a3)
{
  int v3; // eax@4
  const char *v4; // ebx@6
  int v5; // eax@6
  signed int v6; // edx@6
  int v7; // eax@7
  int v8; // eax@8
  const char *v9; // ebx@11
  int v10; // eax@11
  signed int v11; // edx@11
  int v12; // eax@12
  int v13; // eax@13
  signed int v14; // ebx@16
  int v15; // eax@16
  signed int v16; // edx@16
  int v17; // eax@19
  signed int v18; // edx@19
  int v19; // eax@20
  int v20; // eax@25
  int i; // esi@28
  float v22; // ST34_4@31
  int v23; // eax@32
  int v24; // edi@34
  int v25; // esi@35
  float v26; // ST34_4@38
  FILE *result; // eax@41
  int v28; // [sp+28h] [bp-400h]@27
  int nbParam; // [sp+2Ch] [bp-3FCh]@27
  int v30; // [sp+30h] [bp-3F8h]@34
  char s; // [sp+40h] [bp-3E8h]@29
  char src; // [sp+140h] [bp-2E8h]@4
  char v33; // [sp+240h] [bp-1E8h]@30
  int v34; // [sp+340h] [bp-E8h]@23
  int v35; // [sp+3A0h] [bp-88h]@23
  char v36; // [sp+3B8h] [bp-70h]@23
  char v37; // [sp+3C0h] [bp-68h]@23
  char v38; // [sp+3C8h] [bp-60h]@23
  int v39; // [sp+3D4h] [bp-54h]@23
  FILE *stream; // [sp+3ECh] [bp-3Ch]@1
  void *v41; // [sp+3F0h] [bp-38h]@1
  int v42; // [sp+3F4h] [bp-34h]@1
  double v43; // [sp+3F8h] [bp-30h]@23
  double value; // [sp+400h] [bp-28h]@29
  int v45; // [sp+408h] [bp-20h]@4
  int indice; // [sp+40Ch] [bp-1Ch]@27
  int v47; // [sp+410h] [bp-18h]@25
  int v48; // [sp+414h] [bp-14h]@32

  stream = 0;
  v42 = 256;
  readIntValues((CFileParser *)&stream, "$DYN_DAT", "REAL $DYN_DAT[%d]", &src, 1, &v47);
  v20 = operator new[](8 * v47, &std::nothrow);
  *((_DWORD *)this + 3) = v20;


  v28 = *((_DWORD *)this + 3);
  nbParam = v47;
  indice = 0;
  if ( v47 > 0 )
  {
    i = 0;
    do
    {
      CFileParser::getLine((CFileParser *)&stream, &s);
      if ( sscanf(&s, "$DYN_DAT[%d]=%lf", &indice, &value) != 2 )

      { // Can't acquire data
        snprintf(&v33, 0x100u, "%s konnte nicht gelesen werden", "$DYN_DAT[%d]=%lf");
        extended_internalError(
      }
      v22 = value;
      *(double *)(v28 + 8 * indice - 8) = v22;
      ++i;
    }
    while ( nbParam != i );
  }

Basically, I don't understand the meaning of:

  *((_DWORD *)this + 3) = v20;

and:

      *(double *)(v28 + 8 * indice - 8) = v22;

Do you have any ideas ?

So far, I think it's a pointer of pointer, but I don't understand "the meaning" of it because it seems like v28 is a "local variable" with unaloccated space ?

Here is the "pseudo code" of the constructor of the object DynDat:

int __cdecl CDynamicData::CDynamicData(int a1)
{
  int result; // eax@1

  result = a1;
  *(_BYTE *)a1 = 0;
  *(_DWORD *)(a1 + 4) = 0;
  *(_DWORD *)(a1 + 8) = 0;
  *(_DWORD *)(a1 + 12) = 0;
  return result;
}

Bonus question: Do you have any idea of the most efficient way to trace back the parsing and use of some values ?

Kind Regards,

  • Pointer arithmetic is the trick. In *((_DWORD *)this + 3) = v20, this is a pointer, so it's actually adding 3*4 = 12 to the pointer. By looking at the constructor, this means it is assigning v20 to the fourth field of that class. – eric.m Jul 4 at 14:46
  • Also v28 is not unallocated space; it's being assigned as v28 = *((_DWORD *)this + 3);, which was previously assigned to v20, which was previously initialized with operator new[](8 * v47, &std::nothrow); – eric.m Jul 4 at 14:48
  • a fleet look says it is allocating memory and saving the pointer to allocated memory in a sturcts third member (this is a struct ) try defining one also collapse all thos @23,@24 etc into an array of bytes/ints/sometype – blabb Jul 4 at 17:56
  • Ok, I think I understand it better, thank you ! Basically, so far, from what I see, the constructor assign pointer to differents allocated memory space of type double, with all the differents data readen – Gautier A. Jul 15 at 8:43
1

the v20 stuff is simply this->mem = new(); where this is a structure of some sort

the dynamicdata constructor you posted is actually filling up a struct with 0

you need to change the int a1 to struct foo* a1

prior to that you need to define the struct in ida

so since it is returning the struct pointer you need to change the return value also as struct foo*

try compiling this code and decompiling it in ida and you will see the decompilation is exactly similar to what you posted

#include <stdio.h>
#include <memory.h>

typedef struct _SOMESTRUCT {
    unsigned int a;
    unsigned int b;
    unsigned int c;
    unsigned int d;
}Sostr,*PSostr;

PSostr foo( PSostr blah) {

    blah->a = 0;
    blah->b = 0;
    blah->c = 0;
    blah->d = 0;
    return blah;
}

int main (void)
{
    Sostr temp = {0xdeadbeef,0xdeadbeef,0xdeadbeef,0xdeadbeef};    
    printf("%08x %08x %08x %08x\n" , temp.a,temp.b,temp.c,temp.d);
    foo(&temp);
    printf("%08x %08x %08x %08x\n" , temp.a,temp.b,temp.c,temp.d);
    return 0;    
}

googling $DYN_DAT appears to turn out lots of info including a .dat file whose data shows $DYN_DAT[] is an array of floats/doubles

so basically it opens the file and checks for the first entry $REAL_DYN_DAT[XXX] where XXX is the size of all $DYN_DAT entries

allocates XXX * 8 size of memory parses the $DYN_DAT entries line by line and stores all the DOuble values it has read

the file appears to be looking like this

REAL $DYN_DAT[xxx] this is the size of all $DYN_DAT
$DYN_DAT[1]=0.xxxxx
$DYN_DAT[2]=0.yyyyy
$DYN_DAT[3]=1.zzzzz
$DYN_DAT[4]=1.aa
$DYN_DAT[5]=0.mmmm ........ $DYN_DAT[xxx} = d.efghijk
  • I think I get it better right now, thank you ! Basically it's reading al the differents data in differents memory space. The structure is then pointing to the differents memories the function allocated ? So far, that's what I think. I also think there's 2 array "of string" and 2 array of double so far, but I might be wrong. Anyway, thank you for your time ! – Gautier A. Jul 15 at 8:45
0

Sorry for posting in Answer section (but i can't post comments without a reputation >= 50)

so after using google a while my knowlege is: its a KUKA robot, $DYN_DAT is part of the $robocor.dat (which also contain other Arrays/Vars) - http://www.wtech.com.tw/public/download/manual/kuka/krc2/System_Variables_manual.pdf: "Contains the model data of the robot, which are required for acceleration adaptation, the higher motion profile and the calculation of kinetic energy (moments of inertia, friction values, etc.)" so $DYN_DAT is an Array of REAL aka double/float64 values and some of them are known - infereable by combining serveral docs spreaded over the internet, its not clear to me if the $DYN_DAT Array is of same and equal meaning for every type of KUKA robot

and i understand that the content of $DYN_DAT is not full documented, and that is what you want

Question:

The given decompiled (always impressed by hex-rays results) code looks like an textfile parser or something, and i don't think that parsing a textfile is your problem here, or? can you provide us with a sample of the $robocor.dat (pastebin.com) to make it clear what we've really got to base on

Ideas:

If im right (and it is an textfile and parsing is no problem) the next thing will be to find out whos using what parts of the $DYN_DAT:

there are several "attack strategies" available but "I've copied the code from the robot and dissasembled" makes i a little bit hard

  1. define a c-header with a fake class that can be loaded into IDA with File/Load file, you can build test project using your fake class to see if the memory layout fits the one in the reverse code
  2. does that mean you can't debug the code running in IDA
  3. Is there an Emulation System cabable of running on pure Windosw/Linux or something?
  4. What tools are using the $robocore/$DYN_DAT - maybe a simpler teaching tool or something is easier to reverse
  5. 32 or 64bit - i think your code is 32bit

Crazy idea: What about a small Challenge homepage, with a selection of KUKA/Robot-Types which shows your current knowledege of the $DYN_DAT line by line, add the ability to upload $robocor.dat files - make it a crowd problem, post it on reddit/serveral KUKA forums, reach faster information from others

Nice and small tutorial about C++ reversing https://blog.0xbadc0de.be/archives/67

memory layout description etc.

static_assert(sizeof(int) == 4, "wrong size"); // are we 32bit
typedef unsigned int _DWORD;
static_assert(sizeof(double*) == sizeof(_DWORD));

//1. find allocation(new) of CDynamicData then you know how many (vtable+)member-bytes the class containts
// give IDA a header with the class then is hex-rays able to give you even better results

#pragma pack(push,1)
class CDynamicData
{
public:
    //already known
    unsigned char unknown0 = 0;
    unsigned char unknown1 = 0;
    unsigned char unknown2 = 0;
    unsigned char unknown3 = 0;
    _DWORD unknown4 = 0;
    _DWORD unknown5 = 0;
    double* dyn_dat_values = nullptr;
    //unsigned char unknown6[x] -> fill that up

    CDynamicData()
    {
       unknown0 = 0;
       unknown4 = 0;
       unknown5 = 0;
       dyn_dat_values = 0;
    }
};
#pragma pack(pop)

void test()
{
    assert(offsetof(CDynamicData, dyn_dat_values) == 12);

    CDynamicData dd;
    void* _this = &dd;

    int v42 = 123456; // readIntValues...

    double* v20 = new (std::nothrow) double[v42];

    //*((_DWORD *)this + 3) = v20;
    assert((char*)&dd.dyn_dat_values == (char*)((_DWORD *)_this + 3));
    dd.dyn_dat_values = v20;

    double* v28 = dd.dyn_dat_values; // in code a int --> int == ptr-value

    double v22 = 123456.0; // scanf...
    //*(double *)(v28 + 8 * indice - 8) = v22;
    //start with pointer to double array, + 8 because of sizeof(double), -8 because of indice starting with 1 not 0
    int indice = 1; //= 1..n
    v28[indice - 1] = v22;
}

beware of thinking that int means value - hex-rays output is high high level asm so every int could also be just a pointer to something

Load C header: https://www.hex-rays.com/products/ida/support/idadoc/1367.shtml i prepared this header-file for IDA: https://pastebin.com/PWNAAj7T, just load before analyze and hex-rays, then you will see much clearer whats happening

then follow every occurence of CDynamicData and tell IDA to use your struct type - that will help alot

  • Hey, your response helped me quite a bit ! Thank you a lot ! So, I think I've found the function pasting the mada into the robots. Here is the prototype of the CmachineData, CRobotInternal and CVectorBase. I've tried to find a way to contact you on ReverseEnginnering to give you the "complete code" (can't really expose it in public) but I didn't find any ways. – Gautier A. Jul 8 at 23:45
  • you should first and always answer the open questions of the others/or just comment, nothing is more anoying then investing time for good answers or questions and then get no direct reply, too many act like this on the internet, everyone earns an answer, normal discussions should stay here, just update your question accordingly, you can send file-download links to my temporary trashmail account 2tm_4pz6ff58u01t@byom.de - just for file downloads, no discussions :) – llm Jul 10 at 7:13
  • Hello ! Yes, you're right, I forgot all my seemliness, I'm sorry. Anyway, I might be a little bit late and I'm sorry, but I just sent you a link to your email adress. I hope it's still up ! – Gautier A. Jul 15 at 8:47
  • "...Basically it's reading al the differents data in differents memory space. The structure is then pointing to the differents memories the function allocated..." thats the 100% case in software :) - so not very clear if you really understood, did you read thorugh the C++ reversing tutorial, you can't get any further if you do not understand 100% of it - take your time, btw: no email – llm Jul 16 at 9:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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