ZaiRoN

Idc script and stack frame variables length

Rating: 4 votes, 2.50 average.
Among all the precious information retrieved by Ida there’s something I always use when I need to study a target: stack frame. It’s quite useful when you want to see the list of parameters and local variables, but it would be great to see the size of each item. Yes, you can get the length but you have to calculate it each time. I sometimes need this kind of information, especially when I have to deal with fixed length buffers. I tried inspecting through some Ida’s menu without luck, it’s strange that Ida doesn’t provide such information so I decided to write a little idc script able to retrieve local *big* buffers. (If there’s an Ida hidden feature please tell me…)
I wanted to attach the original script I wrote here, but I think it’s much more useful to explain some details about the functions I used leaving the script to you as an exercize. In this simple example I’ll show you how to find out the length of each item inside a stack frame. Let’s start with a simple function:


The stack frame created by Ida is divided into some parts, it looks like a sequence of fields:
- local variables
- saved registers
- return address
- function parameters

Looking at the picture above is pretty easy to locate local variables (ObjectAttributes, KeyValueInformationLength, ResultLength) and function parameters (Handle, ValueName). Moreover you can guess the length of each item. According to the four parts I mentioned above there are some more items that are not specified by Ida, I’m referring to “saved registers” and “return address”. If you look at the offset of each item you’ll surely find out something odd. Look at the gap between ResultLength and Handle: 0×0C bytes. 4 bytes are reserved for ResultLength variable, but there are 8 unreferenced bytes. It’s time to take a look at the stack frame window (ctrl-k):


Here is the answer. Ida uses two special fields named ” r” and ” s”, the length of each field is 4 bytes. They are the “return address” and the “saved registers”.

Ok, how to get the size of the items using an idc script? As you can see from the picture the stack frame looks like a structure definition, the idea is to read each item in sequence.
Code:
#include <idc.idc>

static main()
{
   auto id, i, firstM, lastM, address;
   auto mName, mSize, mFlag;
   
   address = 0×00013C92;        //    Address of the function to check
   id = GetFrame(address);
   firstM = GetFirstMember(id);
   lastM = GetLastMember(id);
   
   for(i=firstM;i<=lastM;i++)
   {
      mName = GetMemberName(id,i);   // Get the name
      mSize = GetMemberSize(id, i);  // Get the size (in byte)
      mFlag = GetMemberFlag(id, i);  // Get the flag
      Message(”\n%s   %d   %x”, mName, mSize, mFlag);
   }
}
First of all I need to get the function frame structure. I use GetFrame, it returns the id of the function frame structure. It’s the first information to retrieve because you need the id when you’ll have to deal with the internal fields of the structure. Once you have the id you can start scanning the entire structure from the first till the last item. GetFirstMember and GetLastMember functions give you the first and the last offset. At this point you can retrieve all the information you need, in this example I get name, size and flag value from every item. The functions I used are GetMemberName, GetMemberSize and GetMemberFlag; pretty intuitive and easy to use. An output line will look like:
Code:
ObjectAttributes   24   60000400
where name=ObjectAttributes, size=24 and flag=60000400. Which kind of information are hidden inside the flag value? idc.idc file contains all the necessary definitions:
Code:
#define FF_DATA 0x00000400L             // Data ?
#define FF_STRU 0×60000000L             // Struct ?
The field contains data and it’s a structure (OBJECT_ATTRIBUTES). And, what about Handle field?
Code:
Handle   4   25500400
Browsing idc.idc file you’ll get:
Code:
#define FF_DATA  0x00000400L            // Data ?
#define FF_0OFF  0×00500000L            // Offset?
#define FF_1OFF  0×05000000L            // Offset?
#define FF_DWRD  0×20000000L            // dword
Ok, there’s only a little behaviour to fix inside the script. Run the script and you’ll see some repeated lines, here’s a snippet taken from the output:
Code:
 …
ObjectAttributes   24   60000400
ObjectAttributes   24   60000400
ObjectAttributes   24   60000400
KeyValueInformationLength   4   20000400
KeyValueInformationLength   4   20000400
KeyValueInformationLength   4   20000400
KeyValueInformationLength   4   20000400
ResultLength   4   20000400
ResultLength   4   20000400
ResultLength   4   20000400
…
Ida repeats the field information on every byte of the field itself. To display only one item per field you can update the ‘i’ variable inside the for statement, add the next line after the Message instruction:
Code:
i = i + GetMemberSize(id, i) - 1;
The example ends here. It works almost fine, but it goes into an infinite loop with certain functions. From what I’ve seen the problem occours when Ida is not able to understand which kind of variable has been declared. Look at this simple example:
Code:
...
INIT:BF9B0786 var_1A4         = dword ptr -1A4h
INIT:BF9B0786 var_18E         = byte ptr -18Eh
INIT:BF9B0786 var_4           = dword ptr -4
…
var_18E is marked as byte but there’s a big gap between var_18E and var_4. Stack frame windows reveals an interesting thing:
Code:
-0000018E var_18E         db ?
-0000018D                 db ? ; undefined
-0000018C                 db ? ; undefined
-0000018B                 db ? ; undefined
-0000018A                 db ? ; undefined
-00000189                 db ? ; undefined
-00000188                 db ? ; undefined
-00000187                 db ? ; undefined
-00000186                 db ? ; undefined
-00000185                 db ? ; undefined
-00000184                 db ? ; undefined
-00000183                 db ? ; undefined
var_18E length is 394 byte and as you can see Ida doesn’t collapse the definition into a single line, but it “explodes” the variable through the 394 bytes.
How can you solve this problem? You can use my initial script adding some more checks. Nothing hard of course, you have all the necessary functions, just use your brain defining a good algo. Hint: take a look at the value returned by GetMemberSize.


Once you have a working script you can extend it covering all the declared functions and filtering the information you’ll get.

Good luck and let me know if you are not able to solve this exercize!!!

Submit "Idc script and stack frame variables length" to Digg Submit "Idc script and stack frame variables length" to del.icio.us Submit "Idc script and stack frame variables length" to StumbleUpon Submit "Idc script and stack frame variables length" to Google

Categories
Uncategorized

Comments