Jump to content
Nytro

[SRC] Length of Function

Recommended Posts

[sRC] Length of Function

FuncLen.cpp

#include <windows.h>
#include <stdio.h>
#include <vector>
#include <iterator>
#include <algorithm>
#include "types.h"
#include "FuncLen.h"



/************************************************************************
Function length calculation algorithm - by Darawk:

1. Scan the function's code for branches, and record each branch. Stop
upon reaching an end-point*. This group of instructions constitutes
the current "block".
2. QSort the branch list
3. Recursively repeat steps 1 & 2 with each branch, skipping duplicates
and intra-block branches.

*end-point: A ret instruction or an unconditional backwards jump,
that jumps to a previous block.
************************************************************************/

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
u32 len = GetFunctionLength(GetProcAddress(GetModuleHandle(moduleName), funcName));

char buf[256] = {0};
sprintf(buf, "%s in %s: %u bytes long", funcName, moduleName, len);
MessageBox(NULL, buf, "Function Length", NULL);

return 0;
}

u32 GetFunctionLength(void *begin)
{
void *end = GetFunctionEnd(begin);
u32 delta = (u32)((DWORD_PTR)end - (DWORD_PTR)begin);
delta += mlde32(end);
return delta;
}

void *GetFunctionEnd(void *func)
{
void *block = func;
vector<void *> branchList;
// ptr now points to the end of this block
void *blockend = GetBranchListFromBlock(block, branchList);

// If there are no branches, then return
// the empty list. If we don't have this
// here the loop will crash on an empty
// branch list.
if(branchList.size() == 0) return blockend;

// Sort the list so that we can identify and
// discard, intra-block branches. And optimize
// the removal of duplicates.
std::sort(branchList.begin(), branchList.end());

void *prev = NULL;
vector<void *>::iterator branch;
for(branch = branchList.begin(); branch != branchList.end(); branch++)
{
// Skip branches that jump into a block we've already
// processed.
if(*branch < blockend || *branch == prev)
continue;

blockend = GetFunctionEnd(*branch);
prev = *branch;
}

return blockend;
}

void *GetBranchListFromBlock(void *block, vector<void *> &branchList)
{
u8 *ptr = (u8 *)block;

// If we reach an end-point, then this block is complete
while(!IsEndPoint(ptr, block))
{
// Record all branching instructions that we encounter
void *address = GetBranchAddress(ptr);
if(address)
{
branchList.push_back(address);
}

// Next instruction
ptr += mlde32(ptr);
}

return ptr;
}


void *GetBranchAddress(u8 *instr)
{
s32 offset = 0;
// This code will determine what type of branch it is, and
// determine the address it will branch to.
switch(*instr)
{
case INSTR_SHORTJMP:
case INSTR_RELJCX:
offset = (s32)(*(s8 *)(instr + 1));
offset += 2;
break;
case INSTR_RELJMP:
offset = *(s32 *)(instr + 1);
offset += 5;
break;
case INSTR_NEAR_PREFIX:
if(*(instr + 1) >= INSTR_NEARJCC_BEGIN && *(instr + 1) <= INSTR_NEARJCC_END)
{
offset = *(s32 *)(instr + 2);
offset += 5;
}
break;
default:
// Check to see if it's in the valid range of JCC values.
// e.g. ja, je, jne, jb, etc..
if(*instr >= INSTR_SHORTJCC_BEGIN && *instr <= INSTR_SHORTJCC_END)
{
offset = (s32)*((s8 *)(instr + 1));
offset += 2;
}
break;
}

if(offset == 0) return NULL;
return instr + offset;
}

bool IsEndPoint(u8 *instr, void *curblock)
{
void *address;
s32 offset;
switch(*instr)
{
case INSTR_RET:
case INSTR_RETN:
case INSTR_RETFN:
case INSTR_RETF:
return true;
break;

// The following two checks, look for an instance in which
// an unconditional jump returns us to a previous block,
// thus creating a pseudo-endpoint.
case INSTR_SHORTJMP:
offset = (s32)(*(s8 *)(instr + 1));
address = instr + offset;
if(address <= curblock) return true;
break;
case INSTR_RELJMP:
offset = *(s32 *)(instr + 1);
address = instr + offset;
if(address <= curblock) return true;
break;
default:
return false;
break;
}

return false;
}

FuncLen.h

using namespace std;

u32 GetFunctionLength(void *begin);
bool IsEndPoint(u8 *instr, void *curblock);
void *FindEndPoint(void *block);
void *GetBranchAddress(u8 *instr);
void *GetNextBlock(u8 *instr, void *curBlockEnd);
void *GetFunctionEnd(void *func);
void ConsolidateBlocks(vector<void *> &blocks);
void *GetBranchListFromBlock(void *block, vector<void *> &branchList);

char funcName[] = "WinExec";
char moduleName[] = "kernel32.dll";

extern "C" int __cdecl mlde32(void *codeptr);

#define INSTR_NEAR_PREFIX 0x0F
#define INSTR_SHORTJCC_BEGIN 0x70
#define INSTR_SHORTJCC_END 0x7F
#define INSTR_NEARJCC_BEGIN 0x80 // Near's are prefixed with a 0x0F byte
#define INSTR_NEARJCC_END 0x8F
#define INSTR_RET 0xC2
#define INSTR_RETN 0xC3
#define INSTR_RETFN 0xCA
#define INSTR_RETF 0xCB
#define INSTR_RELJCX 0xE3
#define INSTR_RELJMP 0xE9
#define INSTR_SHORTJMP 0xEB

mlde32.obj is included in archieve or from download //www.darawk.com/code/FuncLen/

Download (cu cont, atasament):

http://www.ic0de.org/showthread.php?10442-SRC-Length-of-Function

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...