PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Estimate function length



wacked
04.11.2015, 22:02
#include <stdlib.h>#include <assert.h>
#include <stdbool.h>
#include <Windows.h>
#include "udis86.h"
#include "funclen.h"


/**
\brief jmp +X == +X + sizeof(jump type) + eip
*/
static size_t get_jump_offset(ud_t* ud, size_t offsetOfInstr);


/**
\todo add loop & jecx (and possibly more) - though both are probably only used to jump back
and currently is_jump is only called to from functions that don't care about that
*/
static bool is_jump(enum ud_mneomic_code op);


static size_t get_jump_offset(ud_t* ud, size_t offsetOfInstr)
{
const struct ud_operand* op = NULL;
for(int i = 0; op = ud_insn_opr(ud, i); i++)
{
if(op->type == UD_OP_JIMM)
{
return op->lval.sdword + offsetOfInstr + ud_insn_len(ud);
}
// all other types are weird jumps, like jumps to a register or to []
}


return 0;
}


static bool is_jump(enum ud_mneomic_code op)
{
return op >= UD_Ijo && op <= UD_Ijmp;
}


static bool is_end_of_function(enum ud_mneomic_code opc, ud_t* ud, size_t furthestJump, size_t instrOffset)
{
if(opc == UD_Iret && furthestJump <= instrOffset)
return true;
else if(opc == UD_Ijmp)
{
const struct ud_operand* op = ud_insn_opr(ud, 0);
if(op->type == UD_OP_MEM || op->type == UD_OP_REG)
return true;
}
// todo: 0xCC ?


return false;
}


size_t estimate_function_length(void* function)
{
size_t furthestJump = 0; //! Functions can have multiple return points. The library assumes that if a RET is hit and a jmp/jcc went over it, this RET isn't the last
unsigned char* p = function;
size_t funcLen = 0;
ud_t ud;


ud_init(&ud);
ud_set_input_buffer(&ud, function, (size_t)function | (PAGE_BOUNDARY - 1)); // Can't read further than page boundary - there be dragons
ud_set_pc(&ud, (uint64_t)function);
ud_set_mode(&ud, 64);
ud_set_syntax(&ud, UD_SYN_INTEL);


while(funcLen < MINIMUM_REQUIRED_FUNCTION_LENGTH_LONG_HOOK && !ud_input_end(&ud))
{
size_t instrLen = 0,
offsetOfInstr = funcLen;
if(!(instrLen = ud_disassemble(&ud)) || ud.error)
return 0;


p += instrLen;
funcLen += instrLen;


printf("%p %s", ud_insn_off(&ud), ud_insn_asm(&ud));


enum ud_mneomic_code op = ud_insn_mnemonic(&ud);
if(is_jump(op))
{
size_t off = get_jump_offset(&ud, offsetOfInstr);
if(off > furthestJump)
furthestJump = off;
}


if(is_end_of_function(op, &ud, furthestJump, offsetOfInstr))
{
printf("end of function\n");
break;
}


printf("\n");
}


return funcLen;
}



#ifndef FUN_LEN_H
#define FUN_LEN_H


#define MINIMUM_REQUIRED_FUNCTION_LENGTH_LONG_HOOK 16


/**
\brief Estimates the function size by checking opcodes until
* an instruction that signifies the end of the function or
* MINIMUM_REQUIRED_FUNCTION_LENGTH_LONG_HOOK bytes were found
If the function has multiple return points estimate_function_length() tries to find the farthest by keeping track of jumps forward
\return 0 on error
*/
static size_t estimate_function_length(void* function);
#endif


Wie man hoffentlich an den includes merkt braucht es die libudis86.

Jut4h.tm
04.11.2015, 22:07
Schöner Post danke!