PDA

View Full Version : Convert IDA HexRays Decompiler source to working C source



kung foo man
1st July 2015, 01:11
Since I just had the question on Steam, I thought we can collect all the quirks of converting decompiled source to working code.

For the beginning, I made this screenshot, which shows the working version and the decompiled one:

Left = working version = https://github.com/kungfooman/libcod/blob/master/libcod.cpp#L1920
Right = decompiled version = http://pastebin.com/a2ydu2NH

872

Since something like
dword_8571428 is internally for HexRays fully correct, it's not helpful in a shared library, since we cannot just tell LD (the linker) to place this variable to that memory location. Hence we need to dereference it like
*(int *)0x08571428

I made a macro for this in config.hpp: https://github.com/kungfooman/libcod/blob/master/config.hpp



#define INT(address) (*(int*)(address))


So we can just write:




INT(0x08571428)

// so this is all the same:
dword_8571428
*(int *)0x08571428
INT(0x08571428)


There are many other types, which can be treated equally, but nobody ever added macros for them, but the principle will be the same. A nice list:



#include <cstdint>

typedef uint8_t CHAR;
typedef uint16_t WORD;
typedef uint32_t DWORD;

typedef int8_t BYTE;
typedef int16_t SHORT;
typedef int32_t LONG;

typedef LONG INT;
typedef INT BOOL;


So you don't need much conversion, when HexRays gives you something like this:


*(_WORD *)(a2 + 8) + 50;

More conversion rules, questions etc. all welcome

filthy_freak_
7th July 2015, 08:00
I'm trying to convert the following to libcod;



int __cdecl sub_809479A(int a1)
{
int result; // eax@1
char s; // [sp+20h] [bp-28h]@2
int v3; // [sp+24h] [bp-24h]@4
char v4; // [sp+28h] [bp-20h]@2
int v5; // [sp+2Ch] [bp-1Ch]@16
int v6; // [sp+30h] [bp-18h]@18
int v7; // [sp+34h] [bp-14h]@20
char v8; // [sp+38h] [bp-10h]@8
char v9; // [sp+39h] [bp-Fh]@12

result = a1;
if ( *(_DWORD *)(a1 + 134212) )
{
memset(&s, 0, 0x1Cu);
v4 = *(_BYTE *)(sub_808FE02(-1653759219 * ((a1 - (signed int)dword_841FB0C) >> 2)) + 212);
if ( !sub_81069A6(-1653759219 * ((a1 - (signed int)dword_841FB0C) >> 2)) )
{
if ( sub_80A1410() < 0.5 )
v3 |= 1u;
if ( sub_80A1410() < 0.5 )
v3 |= 0x28u;
if ( sub_80A1410() >= 0.33000001 )
{
if ( sub_80A1410() < 0.5 )
v8 = -127;
}
else
{
v8 = 127;
}
if ( sub_80A1410() >= 0.33000001 )
{
if ( sub_80A1410() < 0.5 )
v9 = -127;
}
else
{
v9 = 127;
}
if ( sub_80A1410() < 0.33000001 )
v5 = (signed int)(sub_80A142E() * 360.0);
if ( sub_80A1410() < 0.33000001 )
v6 = (signed int)(sub_80A142E() * 360.0);
if ( sub_80A1410() < 0.33000001 )
v7 = (signed int)(sub_80A142E() * 360.0);
}
*(_DWORD *)(a1 + 134408) = *(_DWORD *)(a1 + 452020) - 1;
result = sub_808F488(a1, (int)&s);
}
return result;
}


but unsure how to convert


v4 = *(_BYTE *)(sub_808FE02(-1653759219 * ((a1 - (signed int)dword_841FB0C) >> 2)) + 212);


I tried


v4 = *(int8_t *)(sub_808FE02(-1653759219 * ((a1 - *(signed int *)0x0841FB0C) >> 2)) + 212);


With no luck. I know its wrong but unsure what it needs to be.

Reason I need this func converted is that with addtestclient() there is a bug that will make hips/legs unaligned from the torso and disabling this function will fix it (However it also disables bot shooting, so I need to rewrite certain parts of the function). Would appreciate it immensely if someone went ahead and converted it all.

OR

Does anyone know a way to make a client shoot their gun?

Ni3ls
7th July 2015, 09:06
/+attack; -attack to shoot?

Tally
7th July 2015, 10:30
Does anyone know a way to make a client shoot their gun?

You can force a player to shoot with clientcmd( "+attack" ), but it doesn't work on bots.

IzNoGoD
7th July 2015, 12:53
Does anyone know a way to make a client shoot their gun?

Try decompiling bullettrace() which should fire a SHOT_MASK. Try replacing that with an actual shot and the bullet fx etc should probably follow

filthy_freak_
7th July 2015, 23:46
Nevermind, with help from izno we've located an interesting function that sets player movements/shoot/ads/angles and successfully disabled the random movement for bots, which has fixed the legs/torso alignment problem =).

If anyone wants to check out the func for their own needs, it is sub_808F488 for 1.0, sub_8090D18 for 1.2 and sub_8090DAC for 1.3.

filthy_freak_
3rd May 2016, 16:19
Some useful IDA macros I thought i'd dump here for future reference;


typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long ulong;

// Partially defined types:
#define _BYTE char
#define _WORD short
#define _DWORD long
#define _QWORD ll
#define _LONGLONG __int128

#ifndef _WINDOWS_
typedef char BYTE;
typedef short WORD;
typedef long DWORD;
typedef long LONG;
#endif
typedef ll QWORD;
#ifndef __cplusplus
typedef int bool; // we want to use bool in our C programs
#endif

// Some convenience macros to make partial accesses nicer
// first unsigned macros:
#define LOBYTE(x) (*((_BYTE*)&(x))) // low byte
#define LOWORD(x) (*((_WORD*)&(x))) // low word
#define LODWORD(x) (*((_DWORD*)&(x))) // low dword
#define HIBYTE(x) (*((_BYTE*)&(x)+1))
#define HIWORD(x) (*((_WORD*)&(x)+1))
#define HIDWORD(x) (*((_DWORD*)&(x)+1))
#define BYTEn(x, n) (*((_BYTE*)&(x)+n))
#define WORDn(x, n) (*((_WORD*)&(x)+n))
#define BYTE1(x) BYTEn(x, 1) // byte 1 (counting from 0)
#define BYTE2(x) BYTEn(x, 2)
#define BYTE3(x) BYTEn(x, 3)
#define BYTE4(x) BYTEn(x, 4)
#define BYTE5(x) BYTEn(x, 5)
#define BYTE6(x) BYTEn(x, 6)
#define BYTE7(x) BYTEn(x, 7)
#define BYTE8(x) BYTEn(x, 8)
#define BYTE9(x) BYTEn(x, 9)
#define BYTE10(x) BYTEn(x, 10)
#define BYTE11(x) BYTEn(x, 11)
#define BYTE12(x) BYTEn(x, 12)
#define BYTE13(x) BYTEn(x, 13)
#define BYTE14(x) BYTEn(x, 14)
#define BYTE15(x) BYTEn(x, 15)
#define WORD1(x) WORDn(x, 1)
#define WORD2(x) WORDn(x, 2) // third word of the object, unsigned
#define WORD3(x) WORDn(x, 3)
#define WORD4(x) WORDn(x, 4)
#define WORD5(x) WORDn(x, 5)
#define WORD6(x) WORDn(x, 6)
#define WORD7(x) WORDn(x, 7)

// now signed macros (the same but with sign extension)
#define SLOBYTE(x) (*((char*)&(x)))
#define SLOWORD(x) (*((short*)&(x)))
#define SLODWORD(x) (*((long*)&(x)))
#define SHIBYTE(x) (*((char*)&(x)+1))
#define SHIWORD(x) (*((short*)&(x)+1))
#define SHIDWORD(x) (*((long*)&(x)+1))
#define SBYTEn(x, n) (*((char*)&(x)+n))
#define SWORDn(x, n) (*((short*)&(x)+n))
#define SBYTE1(x) SBYTEn(x, 1)
#define SBYTE2(x) SBYTEn(x, 2)
#define SBYTE3(x) SBYTEn(x, 3)
#define SBYTE4(x) SBYTEn(x, 4)
#define SBYTE5(x) SBYTEn(x, 5)
#define SBYTE6(x) SBYTEn(x, 6)
#define SBYTE7(x) SBYTEn(x, 7)
#define SBYTE8(x) SBYTEn(x, 8)
#define SBYTE9(x) SBYTEn(x, 9)
#define SBYTE10(x) SBYTEn(x, 10)
#define SBYTE11(x) SBYTEn(x, 11)
#define SBYTE12(x) SBYTEn(x, 12)
#define SBYTE13(x) SBYTEn(x, 13)
#define SBYTE14(x) SBYTEn(x, 14)
#define SBYTE15(x) SBYTEn(x, 15)
#define SWORD1(x) SWORDn(x, 1)
#define SWORD2(x) SWORDn(x, 2)
#define SWORD3(x) SWORDn(x, 3)
#define SWORD4(x) SWORDn(x, 4)
#define SWORD5(x) SWORDn(x, 5)
#define SWORD6(x) SWORDn(x, 6)
#define SWORD7(x) SWORDn(x, 7)