Nytro Posted June 19, 2011 Report Posted June 19, 2011 [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 list3. 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.husing 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 0xEBmlde32.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 Quote