[IDC] Tiny script automatically naming ~300 functions by parsing debug strings

Posts 1–15 of 19 · Page 1 of 2
[IDC] Tiny script automatically naming ~300 functions by parsing debug strings
Yo MPGH!

I guess that most of you won't know me, as I wasn't very active over here in the past due to some private reasons, but I said to myself: "Why not giving the guys over there a shot by releasing some stuff and see what they do with it.".

Beforehand: if you have no clue about how to use IDA and what the fuck I'm talking about: please don't tire me with silly questions.

I started divin' into CF reverse engineering (with varying activity) about a month ago and the first thing I realized was that, in many cases, it's very easy to find out what the game's code is good for due to the nice "commenting" with debug strings used by the CrossFire developers literally everywhere. There's one function I use to call LogActionf (probably no perfect name as it actually does not log anything but pushes the given format string into CrossFire's debug console), that is used all over the code, probably prototyped somehow like this:
Code:
void LogActionf(const char *szFormat, ...);
Furthermore, there is the following format string used in 543 cases
Code:
LT ERROR: %s returned %s (%s)
where the first placeholder is filled with the calling function's name, the second one with some kind of error "descriptor" (e.g. LT_NOTFOUND) and the third one with a string describing the error. To this format string, in turn, a pointer is addressed which I labeled pLtErrorSReturn. Using this simple logic the script later in this post is able to rename a whole bunch of functions in the game to something better fitting than sub_XXXXXX.

tl;dr:
  1. Locate format string (LT ERROR: %s returned %s (%s))
  2. Check X-Refs for a data reference (pointer to format-string)
  3. Take a look at the X-Refs to the pointer and see what function it is pushed to (will be LogActionf)
  4. Rename the format-string ptr to pLtErrorSReturn and the function it is pushed to to LogActionf
  5. Fire script and admire how it gives ~300 functions correct names


Code:
#include <idc.idc>

static main()
{
   auto  strAddr     = LocByName("pLtErrorSReturn"), 
         logFunAddr  = LocByName("LogActionf"), 
         curXref, 
         curAddr,
         curTraceAddr,
         firstParamFound,
         funcNameStrAddr,
         regId,
         funAddr,
         funName,
         oldFunName;
      
   for(curXref = DfirstB(strAddr)
      ; curXref != BADADDR
      ; curXref = DnextB(strAddr, curXref))
   {
      // locate function name
      // ------------------------------------------------
   
      // Check mnemonic
      if (GetMnem(curXref) != "mov" 
         || GetOpType(curXref, 0) != o_reg
         || GetOpType(curXref, 1) != o_mem)
      {
         Message("[0x%08X] referencing instruction is not \"mov eXx, [mem]\"!\n", curXref);
         continue;
      }
      
      // Find LogActionf call (max 50 bytes away)
      for (curAddr = curXref
         ; curAddr != BADADDR
         ; curAddr = NextAddr(curAddr))
      {
         // Is call to log fun? Break loop
         if (GetMnem(curAddr) == "call" 
            && GetOpnd(curAddr, 0) == "LogActionf")
         {
            break;
         }
         
         if (curAddr - curXref > 50)
         {
            Message("[0x%08X] too many steps till LogActionf call\n", curXref);
            return;
         }
      }
      
      // Find LogActionf's second parameter
      for (firstParamFound = 0; curAddr != BADADDR; curAddr = PrevAddr(curAddr))
      {
         // Conditional?
         if (RfirstB0(curAddr) != BADADDR)
         {
            Message("[0x%08X] conditional situation\n", curAddr);
            break;
         }
         
         // Desired parameter?
         if (GetMnem(curAddr) == "push")
         {
            if (!firstParamFound)
               firstParamFound = 1;
            else
            {
               funcNameStrAddr = 0;
            
               // In case the operand is a register, we have to trace what
               // is written into it
               if (GetOpType(curAddr, 0) == o_reg)
               {
                  regId = GetOperandValue(curAddr, 0);
                                    
                  for (curTraceAddr = curAddr
                     ; curTraceAddr != BADADDR
                     ; curTraceAddr = PrevAddr(curTraceAddr))
                  {
                     // Does instruction write into our register?
                     if (GetOpType(curTraceAddr, 0) == o_reg
                        && GetOperandValue(curTraceAddr, 0) == regId
                        && GetOpType(curTraceAddr, 1) == o_mem)
                     {
                        funcNameStrAddr = Dword(GetOperandValue(curTraceAddr, 1));
                        break;
                     }
                     
                     // Max. trace distance = 50 non-conditional bytes
                     if (curAddr - curTraceAddr > 50 || RfirstB0(curTraceAddr) != BADADDR)
                     {
                        Message("[0x%08X] conditional situation or trace width exceeded\n", 
                                curTraceAddr);
                        break;
                     }
                  }
               } 
               else if (GetOpType(curAddr, 0) == o_imm)
                  funcNameStrAddr = GetOperandValue(curAddr, 0);
               else
               {
                  Message("[0x%08X] unsupported operand\n", curAddr);
                  return;
               }
               
               // check if string contains spaces (filter out names with comments)
               funName = 0;
               if (funcNameStrAddr)
               {
                  if (strstr(GetString(funcNameStrAddr, -1, ASCSTR_C), " ") != -1)
                  {
                     Message("[0x%08X] no valid function name\n", curAddr);
                     funcNameStrAddr = 0;
                  }
                  else
                     funName = GetString(funcNameStrAddr, -1, ASCSTR_C);
               }
                  
               break;
            }
         }
      }
      
      // rename function
      // ------------------------------------------------
      
      // only if function's name could be determined
      if (funName)
      {   
         oldFunName = GetFunctionName(curXref);
         
         if (oldFunName != "" && !hasName(GetFlags(LocByName(oldFunName))))
         {
            // make name unique
            while (LocByName(funName) != BADADDR)
               funName = funName + "_";
         
            Message("[0x%08X] %s => %s\n", LocByName(oldFunName), oldFunName, funName);
            MakeNameEx(LocByName(oldFunName), funName, SN_CHECK | SN_NON_AUTO);
         }
      }
      
      // ------------------------------------------------
      
   }
   
   Message("Done, leaving.\n");
} // ==> main
Hope you have some use for that!

Greets,
Ende! - **** team
i Have question i pm you
nice work.. i hope you make one for ollydbg too
Quote Originally Posted by giniyat101 View Post
nice work.. i hope you make one for ollydbg too
Honestly I'm no big fan of OllyDbg in regards of reverse eningeering contexts - I prefer static analysis using IDA. So I'm sorry to tell you that this probably won't happen.
Quote Originally Posted by Ende! View Post
Yo MPGH!

I guess that most of you won't know me, as I wasn't very active over here in the past due to some private reasons, but I said to myself: "Why not giving the guys over there a shot by releasing some stuff and see what they do with it.".

Beforehand: if you have no clue about how to use IDA and what the fuck I'm talking about: please don't tire me with silly questions.

I started divin' into CF reverse engineering (with varying activity) about a month ago and the first thing I realized was that, in many cases, it's very easy to find out what the game's code is good for due to the nice "commenting" with debug strings used by the CrossFire developers literally everywhere. There's one function I use to call LogActionf (probably no perfect name as it actually does not log anything but pushes the given format string into CrossFire's debug console), that is used all over the code, probably prototyped somehow like this:
Code:
void LogActionf(const char *szFormat, ...);
Furthermore, there is the following format string used in 543 cases
Code:
LT ERROR: %s returned %s (%s)
where the first placeholder is filled with the calling function's name, the second one with some kind of error "descriptor" (e.g. LT_NOTFOUND) and the third one with a string describing the error. To this format string, in turn, a pointer is addressed which I labeled pLtErrorSReturn. Using this simple logic the script later in this post is able to rename a whole bunch of functions in the game to something better fitting than sub_XXXXXX.

tl;dr:
  1. Locate format string (LT ERROR: %s returned %s (%s))
  2. Check X-Refs for a data reference (pointer to format-string)
  3. Take a look at the X-Refs to the pointer and see what function it is pushed to (will be LogActionf)
  4. Rename the format-string ptr to pLtErrorSReturn and the function it is pushed to to LogActionf
  5. Fire script and admire how it gives ~300 functions correct names


Code:
#include <idc.idc>

static main()
{
   auto  strAddr     = LocByName("pLtErrorSReturn"), 
         logFunAddr  = LocByName("LogActionf"), 
         curXref, 
         curAddr,
         curTraceAddr,
         firstParamFound,
         funcNameStrAddr,
         regId,
         funAddr,
         funName,
         oldFunName;
      
   for(curXref = DfirstB(strAddr)
      ; curXref != BADADDR
      ; curXref = DnextB(strAddr, curXref))
   {
      // locate function name
      // ------------------------------------------------
   
      // Check mnemonic
      if (GetMnem(curXref) != "mov" 
         || GetOpType(curXref, 0) != o_reg
         || GetOpType(curXref, 1) != o_mem)
      {
         Message("[0x%08X] referencing instruction is not \"mov eXx, [mem]\"!\n", curXref);
         continue;
      }
      
      // Find LogActionf call (max 50 bytes away)
      for (curAddr = curXref
         ; curAddr != BADADDR
         ; curAddr = NextAddr(curAddr))
      {
         // Is call to log fun? Break loop
         if (GetMnem(curAddr) == "call" 
            && GetOpnd(curAddr, 0) == "LogActionf")
         {
            break;
         }
         
         if (curAddr - curXref > 50)
         {
            Message("[0x%08X] too many steps till LogActionf call\n", curXref);
            return;
         }
      }
      
      // Find LogActionf's second parameter
      for (firstParamFound = 0; curAddr != BADADDR; curAddr = PrevAddr(curAddr))
      {
         // Conditional?
         if (RfirstB0(curAddr) != BADADDR)
         {
            Message("[0x%08X] conditional situation\n", curAddr);
            break;
         }
         
         // Desired parameter?
         if (GetMnem(curAddr) == "push")
         {
            if (!firstParamFound)
               firstParamFound = 1;
            else
            {
               funcNameStrAddr = 0;
            
               // In case the operand is a register, we have to trace what
               // is written into it
               if (GetOpType(curAddr, 0) == o_reg)
               {
                  regId = GetOperandValue(curAddr, 0);
                                    
                  for (curTraceAddr = curAddr
                     ; curTraceAddr != BADADDR
                     ; curTraceAddr = PrevAddr(curTraceAddr))
                  {
                     // Does instruction write into our register?
                     if (GetOpType(curTraceAddr, 0) == o_reg
                        && GetOperandValue(curTraceAddr, 0) == regId
                        && GetOpType(curTraceAddr, 1) == o_mem)
                     {
                        funcNameStrAddr = Dword(GetOperandValue(curTraceAddr, 1));
                        break;
                     }
                     
                     // Max. trace distance = 50 non-conditional bytes
                     if (curAddr - curTraceAddr > 50 || RfirstB0(curTraceAddr) != BADADDR)
                     {
                        Message("[0x%08X] conditional situation or trace width exceeded\n", 
                                curTraceAddr);
                        break;
                     }
                  }
               } 
               else if (GetOpType(curAddr, 0) == o_imm)
                  funcNameStrAddr = GetOperandValue(curAddr, 0);
               else
               {
                  Message("[0x%08X] unsupported operand\n", curAddr);
                  return;
               }
               
               // check if string contains spaces (filter out names with comments)
               funName = 0;
               if (funcNameStrAddr)
               {
                  if (strstr(GetString(funcNameStrAddr, -1, ASCSTR_C), " ") != -1)
                  {
                     Message("[0x%08X] no valid function name\n", curAddr);
                     funcNameStrAddr = 0;
                  }
                  else
                     funName = GetString(funcNameStrAddr, -1, ASCSTR_C);
               }
                  
               break;
            }
         }
      }
      
      // rename function
      // ------------------------------------------------
      
      // only if function's name could be determined
      if (funName)
      {   
         oldFunName = GetFunctionName(curXref);
         
         if (oldFunName != "" && !hasName(GetFlags(LocByName(oldFunName))))
         {
            // make name unique
            while (LocByName(funName) != BADADDR)
               funName = funName + "_";
         
            Message("[0x%08X] %s => %s\n", LocByName(oldFunName), oldFunName, funName);
            MakeNameEx(LocByName(oldFunName), funName, SN_CHECK | SN_NON_AUTO);
         }
      }
      
      // ------------------------------------------------
      
   }
   
   Message("Done, leaving.\n");
} // ==> main
Hope you have some use for that!

Greets,
Ende! - **** team
why not you post all these on your site ? as i see your admin there ...
lol
Quote Originally Posted by BlackLite View Post
why not you post all these on your site ? as i see your admin there ...
lol
Why would I do that? There's nobody over there who could have any use for it. 'My' site is not intended to step into competition with sites like MPGH, it's more like a support and release board for our hacks.
Quote Originally Posted by Ende! View Post
Why would I do that? There's nobody over there who could have any use for it. 'My' site is not intended to step into competition with sites like MPGH, it's more like a support and release board for our hacks.
my name there helm i buy farmbot there :P for my 2 computers i pay 25euro psc + 10usd on paypal
@Ende!
1. Good work! It's interesting
2. Why are you with ****?
- they bought the VIP source from @Zacherl (yeah i know that.. by contacts)
. - now they are not able to Update becouse cf patched the d3d9.dll entry (Midfunc Hook)
. - at last, the source of them is written in Delphi (omg)
3. I will stay on ollydbg but if you think IDA is better, its okay, i never tryed it becouse i can't find an cracked version of it.
@BlackLite
1. QQ more, if you don't understand it.. "psssst, i have an tipp for you > leave coding section > go to tutorial section > open up a thread > teach yourselfe coding & understanding posts about developing and such"
2. leechers like you mages me like *fuck yea, i make bitches wet*
Quote Originally Posted by Code[VB] View Post
@Ende!
1. Good work! It's interesting
2. Why are you with ****?
- they bought the VIP source from @Zacherl (yeah i know that.. by contacts)
. - now they are not able to Update becouse cf patched the d3d9.dll entry (Midfunc Hook)
. - at last, the source of them is written in Delphi (omg)
3. I will stay on ollydbg but if you think IDA is better, its okay, i never tryed it becouse i can't find an cracked version of it.
@BlackLite
1. QQ more, if you don't understand it.. "psssst, i have an tipp for you > leave coding section > go to tutorial section > open up a thread > teach yourselfe coding & understanding posts about developing and such"
2. leechers like you mages me like *fuck yea, i make bitches wet*
lol ? nice useless thread ... i didnt type anything like coding ? and as i told u GTFO TO UR CRAP GK NOOOOOB.
MPGH DONT NEED NOOBS LIKE U.
Quote Originally Posted by BlackLite View Post
lol ? nice useless thread ... i didnt type anything like coding ? and as i told u GTFO TO UR CRAP GK NOOOOOB.
MPGH DONT NEED NOOBS LIKE U.
baahh words from a hobby-less little kid
you should first think about what your going to write here

come on.. just a little prove by my side

my team vips are coming out soon:
- cf na
- cf ru
- cf ph
- cf eu
- cf fg

screen is from cf fg becouse that was the one i updated yesterday
(menu is just a simple basic from my side becouse we only need to testup the features etc, the real vip is looking better)

(there is no advertise on it so, no bann reason for me > just look at that site @BlackLite named and you will see identical pictures & threads)

my job here:
- helped G-Force (when i was noob)
- posted my hacks and worked with my bros @derh.acker & @Skrillex
- i know now more about coding than about 3 years ago
- yeah i´m still learning that my skill grows (C++ & ASM books)
- i never will post here on mpgh again becouse the rules are to bad for my releases.. i can´t use my loader (more than 1000 lines perfect code) and and and.. and i hate leechers like you @BlackLite becouse you can see tons of it here on mpgh


also my last word here.. if i meet you at gk i will f*** y** in your a** and give you instant bann



Quote Originally Posted by Code[VB] View Post
@Ende!
1. Good work! It's interesting
2. Why are you with ****?
- they bought the VIP source from @Zacherl (yeah i know that.. by contacts)
. - now they are not able to Update becouse cf patched the d3d9.dll entry (Midfunc Hook)
. - at last, the source of them is written in Delphi (omg)
3. I will stay on ollydbg but if you think IDA is better, its okay, i never tryed it becouse i can't find an cracked version of it.
@BlackLite
1. QQ more, if you don't understand it.. "psssst, i have an tipp for you > leave coding section > go to tutorial section > open up a thread > teach yourselfe coding & understanding posts about developing and such"
2. leechers like you mages me like *fuck yea, i make bitches wet*
OFFTOPIC: lol they really use delphi to make d3d hacks ?
Quote Originally Posted by Code[VB] View Post
baahh words from a hobby-less little kid
you should first think about what your going to write here

come on.. just a little prove by my side

my team vips are coming out soon:
- cf na
- cf ru
- cf ph
- cf eu
- cf fg

screen is from cf fg becouse that was the one i updated yesterday
(menu is just a simple basic from my side becouse we only need to testup the features etc, the real vip is looking better)

(there is no advertise on it so, no bann reason for me > just look at that site @BlackLite named and you will see identical pictures & threads)

my job here:
- helped G-Force (when i was noob)
- posted my hacks and worked with my bros @derh.acker & @Skrillex
- i know now more about coding than about 3 years ago
- yeah i´m still learning that my skill grows (C++ & ASM books)
- i never will post here on mpgh again becouse the rules are to bad for my releases.. i can´t use my loader (more than 1000 lines perfect code) and and and.. and i hate leechers like you @BlackLite becouse you can see tons of it here on mpgh


also my last word here.. if i meet you at gk i will f*** y** in your a** and give you instant bann



idc about all your shit or you fucking ugly site and i dont even visit it ... LOL hum u say me leecher ? lalz 2 kids gtfo from mpgh go at your site noobs and i dont give a fuck about gforce

---------- Post added at 07:07 AM ---------- Previous post was at 07:06 AM ----------

Quote Originally Posted by |Skrillex| View Post
@Ende! nice its very usefull..Weiter so
@BlackLite u are only a fucking leecher!U cant code anything ..U ask for source thats a fail xD go learn c++ dumbass xD
"In GK are only pro coders but mpgh full with leechers (but not all) u are only one of the leechers."
who give a fuck or mention a gay like u ? LOLOLOL Seems ur friend dont know to answer me
@Ende! nice its very usefull..Weiter so
@BlackLite u are only a fucking leecher!U cant code anything ..U ask for source thats a fail xD go learn c++ dumbass xD
"In GK are only pro coders but mpgh full with leechers (but not all) u are only one of the leechers."
man


Code[VB] plz
(Download (Download (Download (Download
Quote Originally Posted by Code[VB] View Post
2. Why are you with ****?
- they bought the VIP source from @Zacherl (yeah i know that.. by contacts)
. - now they are not able to Update becouse cf patched the d3d9.dll entry (Midfunc Hook)
. - at last, the source of them is written in Delphi (omg)
They only used my old text based menu, because they need a quick release. They are actually very skilled. As you can see in the newer versions of the hack, Saedelaere coded a complete new mouse menu.

Quote Originally Posted by kmanev073 View Post
OFFTOPIC: lol they really use delphi to make d3d hacks ?
BTW: Delphi is a very nice language. It really doesnt matter whether you use delphi or C++ for hacks. It only depends on what you like more, the delphi or the C++ syntax.
Posts 1–15 of 19 · Page 1 of 2

Post a Reply

Similar Threads

Tags for this Thread

None

Talk with us