首页
社区
课程
招聘
[原创]反汇编中计算函数大小
发表于: 2013-5-7 20:22 6658

[原创]反汇编中计算函数大小

2013-5-7 20:22
6658
第一次发原创贴,写得很搓,不要喷我

好了,废话不多说,回归正题,今天无聊,写了个得到函数体具体长度的代码大概测试了,还勉强可用.
这玩意谈不上什么算法,就是逐条指令扫描,遇到短跳转就记录到一个链表中保存起来,然后继续。
遇到ret指令就查询链表,看是否结束了,否则继续...大概就是这样的,不知道大家能不能看懂

代码很简单很搓,有很多情况没有考虑进去,希望大家多多指教,谢谢.

#define GetShortOffset(addr) *(char*)( (addr) + 1 )
#define GetShortAddr(addr) (addr) + GetShortOffset(addr) + 2

enum _MACHINE_CODE{
	OPCODE_EB	= 0xEB,
	OPCODE_PUSH = 0x68,
	OPCODE_CALL = 0xE8,
	OPCODE_JMP	= 0xE9,
	OPCODE_JO	= 0x70,
	OPCODE_JNO,
	OPCODE_JB,
	OPCODE_JNB,
	OPCODE_JE,
	OPCODE_JNZ,
	OPCODE_JBE,
	OPCODE_JA,
	OPCODE_JS,
	OPCODE_JNS,
	OPCODE_JPE,
	OPCODE_JPO,
	OPCODE_JL,
	OPCODE_JGE,
	OPCODE_JLE,
	OPCODE_JG,
	OPCODE_JO_LONG	= 0x800F ,
	OPCODE_JNO_LONG	= 0x810F ,
	OPCODE_JB_LONG	= 0x820F ,
	OPCODE_JNB_LONG	= 0x830F ,
	OPCODE_JE_LONG	= 0x840F ,
	OPCODE_JNZ_LONG	= 0x850F ,
	OPCODE_JBE_LONG	= 0x860F ,
	OPCODE_JA_LONG	= 0x870F ,
	OPCODE_JS_LONG	= 0x880F ,
	OPCODE_JNS_LONG	= 0x890F ,
	OPCODE_JPE_LONG	= 0x8A0F ,
	OPCODE_JPO_LONG	= 0x8B0F ,
	OPCODE_JL_LONG	= 0x8C0F ,
	OPCODE_JGE_LONG	= 0x8D0F ,
	OPCODE_JLE_LONG	= 0x8E0F ,
	OPCODE_JG_LONG	= 0x8F0F 
};

#define CASESHORTADDR case OPCODE_EB:	\
case OPCODE_JO:		\
case OPCODE_JNO:	\
case OPCODE_JB:		\
case OPCODE_JNB:	\
case OPCODE_JE:		\
case OPCODE_JNZ:	\
case OPCODE_JBE:	\
case OPCODE_JA:		\
case OPCODE_JS:		\
case OPCODE_JNS:	\
case OPCODE_JPE:	\
case OPCODE_JPO:	\
case OPCODE_JL:		\
case OPCODE_JGE:	\
case OPCODE_JLE:	\
case OPCODE_JG:


ULONG GetProcSize(PUCHAR Opcode){ 
	ULONG					iOffSet = 0;
	ULONG					iOpcodeOfSize = 0;
	ULONG					iStart = (ULONG)Opcode;
	LONG					addr ;
	PSHORT_JUMP_ADDR_LIST	ListHead = NULL;
	PSHORT_JUMP_ADDR_LIST	pCurrent = NULL; 
	BOOL					bNext = TRUE;

	
	InitializeList ( ListHead ,pCurrent,SHORT_JUMP_ADDR_LIST ) ;
	
	do 
	{
		addr = 0;
		iOpcodeOfSize = GetOpCodeSize( Opcode + iOffSet );
		switch( *(BYTE*)( Opcode + iOffSet ) ){ 
			CASESHORTADDR; { 
				if ( iOpcodeOfSize != 2 )
					break;
				addr = GetShortAddr( (LONG)Opcode + iOffSet  ) ;
				if ( iStart > addr ) // 说明这个跳转超出了函数头,直接不管
					break;
				// 重复的不记录
				if ( FindDuplicate( ListHead, addr ) )
					break;
				PSHORT_JUMP_ADDR_LIST p = (PSHORT_JUMP_ADDR_LIST)malloc( sizeof(SHORT_JUMP_ADDR_LIST) );
				if ( !p ){
					iOffSet = 0;
					goto eXit0;
				}
				p->pos = addr ;
				InsertList( p,pCurrent ); 
				__DEBUG(DebugPrint("[*] Short Address:0x%08x\r\n" , p->pos ));
			}
			break; 
		case 0xC3:
		case 0xC2: {
				// 在链表中查找这个地址是否大于所有跳转,如果是,说明函数结束
				if ( DetectedEnd( ListHead, (LONG)Opcode + iOffSet ) ){
					bNext = FALSE;
					__DEBUG(DebugPrint("[*] End address:0x%08X\r\n" ,(LONG)Opcode + iOffSet ));
				}
			}
			break;
		}
		iOffSet += iOpcodeOfSize ; 
	} 
	while ( bNext );

eXit0:	
	ReleaseListResource( ListHead );
	return iOffSet;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 6
支持
分享
最新回复 (9)
雪    币: 1233
活跃值: (907)
能力值: ( LV12,RANK:750 )
在线值:
发帖
回帖
粉丝
2
哈哈,一般情况下这样干就可以了
http://opscn.sinaapp.com/showthread.php?tid=51&pid=72
2013-5-7 22:50
0
雪    币: 371
活跃值: (72)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
3
的确,一般都这样干,欢迎更好的点子~~~
2013-5-7 22:56
0
雪    币: 239
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
mark,学习
2013-5-7 23:22
0
雪    币: 88
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
弱弱的回下,这个局限比较大呀,不是我理想的
2013-5-7 23:30
0
雪    币: 50
活跃值: (10)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
6
这个对一般的dll貌似不太好吧,如果涉及到远跳或者调用别的函数
2013-5-8 08:15
0
雪    币: 204
活跃值: (1668)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
正好需要这个,以前也写过后来忘记不知道放哪了,多谢楼主,收下了
2013-5-8 08:31
0
雪    币: 1233
活跃值: (907)
能力值: ( LV12,RANK:750 )
在线值:
发帖
回帖
粉丝
8
我不知道你计算函数大小用来干嘛的,我是用在堆栈搜索用的,大部分内核函数应该都可以用,
实际上你可以用IDA看看,大部分编译后的可执行档都是16字节nop 或者 cc补齐的。此特征
定位应该还是蛮实用的,你那样做复杂且暂时不支持x64吧?
2013-5-8 09:00
0
雪    币: 215
活跃值: (90)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
9
算函数大小没多大意思,做个像IDA里的Wingraph那样代码分块图那种就实用了。这样就可以分析单个函数
而不用整个模块文件的分析。
2013-5-8 09:26
0
雪    币: 88
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
谢谢大家的指教。
我写这个的初衷只是想用来进行函数内的hook检查比对。我们的实际需求决定代码的逻辑.
没有什么高深的技术,适合自己才最好吧.一步一步来,希望有时间有好心情,写出更好的
东西.
2013-5-8 14:00
0
游客
登录 | 注册 方可回帖
返回
//