能力值:
( LV17,RANK:797 )
|
-
-
2 楼
IDA 有时候识别都不太准确
|
能力值:
( LV13,RANK:270 )
|
-
-
3 楼
一楼老哥,我只想识别Kernel32.dll中的函数。这些函数应该是比较规范的,没有乱起八糟的混淆。
|
能力值:
( LV5,RANK:73 )
|
-
-
4 楼
识别别人的函数长度是没法做到百分百准确的,可以参考前辈的文章:https://bbs.pediy.com/thread-102977.htm
|
能力值:
( LV7,RANK:102 )
|
-
-
5 楼
应该就是控制流程图的生成----Control Flow Graph,一般情况都是可以识别的,但是特殊情况却很难处理。参考x64dbg中的Graph生成代码,和IDA的控制流程图生成。
|
能力值:
( LV1,RANK:0 )
|
-
-
6 楼
函数的表现形式是字节,要统计大小那也只能是统计这个函数的入口地址到结束地址占用的字节数,我理解在函数的入口地址-ret的地址之间的字节数量不就是函数的大小吗?
|
能力值:
( LV5,RANK:73 )
|
-
-
7 楼
我来自南方
函数的表现形式是字节,要统计大小那也只能是统计这个函数的入口地址到结束地址占用的字节数,我理解在函数的入口地址-ret的地址之间的字节数量不就是函数的大小吗? ...
jxx $L1
ret
$L1:
...
ret 这种情况就炸了
最后于 2020-10-11 02:48
被Sprite雪碧编辑
,原因:
|
能力值:
( LV2,RANK:10 )
|
-
-
8 楼
你能告诉我有什么作用?如果没什么用,就是花架子,建议别搞。
|
能力值:
( LV13,RANK:270 )
|
-
-
9 楼
我来自南方
函数的表现形式是字节,要统计大小那也只能是统计这个函数的入口地址到结束地址占用的字节数,我理解在函数的入口地址-ret的地址之间的字节数量不就是函数的大小吗?
但可能存在多个ret
|
能力值:
( LV13,RANK:270 )
|
-
-
10 楼
tDasm
你能告诉我有什么作用?如果没什么用,就是花架子,建议别搞。
我研究上需要用到
|
能力值:
( LV13,RANK:270 )
|
-
-
11 楼
Sprite雪碧
识别别人的函数长度是没法做到百分百准确的,可以参考前辈的文章:https://bbs.pediy.com/thread-102977.htm
谢谢老哥
|
能力值:
( LV9,RANK:280 )
|
-
-
12 楼
x64可以从pdata里识别
|
能力值:
( LV5,RANK:60 )
|
-
-
13 楼
微软编译的函数也有看上去不太标准的,ntoskrnl里面就见过几个在不同区段间跳转的函数,而且跳转地址比函数入口还小,单纯比较max{retaddress}肯定行不通的
|
能力值:
( LV2,RANK:10 )
|
-
-
14 楼
|
能力值:
( LV13,RANK:270 )
|
-
-
15 楼
tDasm
要有用才值得研究。你都不知道那就说明毫无作用。
行吧
|
能力值:
( LV2,RANK:10 )
|
-
-
16 楼
x64里面的 pdata的 Runtime_Function
|
能力值:
( LV3,RANK:20 )
|
-
-
17 楼
我写过这个功能, 就输入一个起始地址, 然后输出函数范围的数组. 主要就遍历条件跳转将目的地址加入todolist, 无条件跳转以及ret类指令当终点, 得到所有的beginrva和endrva之后, 判断是否有重叠, 有重叠就合成. 之后就根据目标汇编代码增加条件跳转的处理, 那种jcc imm的好处理, 很多其他的mov r32,xx再jmp r32这种就看情况一个个情况加.
最后于 2020-10-12 10:49
被boursonjane编辑
,原因:
|
能力值:
( LV3,RANK:20 )
|
-
-
18 楼
#define GE_X_LE(a,x,b) (((x)>=(a)) && ((x) <= (b)))
#define GE_X_LS(a,x,b) (((x)>=(a)) && ((x) < (b)))
#define GT_X_LE(a,x,b) (((x)> (a)) && ((x) <= (b)))
#define GT_X_LS(a,x,b) (((x)> (a)) && ((x) < (b)))
typedef struct range
{
DWORD startrva;
DWORD dwsize;
DWORD endrva; //endrva = startrva + dwsize - 1
}*prange;
int myidgroup1[] =
{
X86_INS_JAE,
X86_INS_JA,
X86_INS_JBE,
X86_INS_JB,
X86_INS_JCXZ,
X86_INS_JECXZ,
X86_INS_JE,
X86_INS_JGE,
X86_INS_JG,
X86_INS_JLE,
X86_INS_JL,
X86_INS_JNE,
X86_INS_JNO,
X86_INS_JNP,
X86_INS_JNS,
X86_INS_JO,
X86_INS_JP,
X86_INS_JRCXZ,
X86_INS_JS,
0
};
int checkid(int id, int* myidset)
{
while (*myidset)
{
if (id == *myidset)
{
return true;
}
++myidset;
}
return false;
}
bool comparer(range& ra, range& rb)
{
return ra.startrva < rb.startrva;
}
bool checkcommon(range& ra, range& rb)
{
if (ra.endrva < rb.startrva - 1 || rb.endrva < ra.startrva - 1)
{
return false;
}
return true;
}
int functionparser::getfuncrange(DWORD dwfuncrva, _Inout_ std::vector<range>& rangelist, BYTE* pebase)
{
csh handle;
cs_insn* insn;
size_t count;
if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK)
return CAPSTONE_FAIL;
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
DWORD dwprevrva = dwfuncrva;
DWORD nextrva = 0;
std::vector<DWORD> todorva;
BYTE* tempdata = NULL;
while (true)
{
for (int i = 0;;)
{
count = cs_disasm(handle, pebase + rva2fo(pebase, dwprevrva) + i, 0x10, dwprevrva + i, 1, &insn);
if (count == 0)
{
tempdata = pebase + rva2fo(pebase, dwprevrva) + i;
//capstone好像没支持这个指令, 我临时修补一下.
//0F 01 FA monitorx rax, rcx, rdx
if (tempdata[0] == 0xf && tempdata[1] == 0x1 && tempdata[2] == 0xfa)
{
i += 3;
continue;
}
//0F 01 FB mwaitx rax, rcx, rbx
if (tempdata[0] == 0xf && tempdata[1] == 0x1 && tempdata[2] == 0xfb)
{
i += 3;
continue;
}
//F3 48 0F 1E CA rdsspq rdx
if (*(DWORD*)tempdata == 0x1e0f48f3 && tempdata[4] == 0xca)
{
i += 5;
continue;
}
}
#pragma region α
////注意 跟β的顺序不能颠倒
//发现条件跳转 或 jmp
if (checkid(insn[0].id,myidgroup1) || insn[0].id == X86_INS_JMP)
{
//得到跳转目标地址
DWORD dwdest = strtoul(insn[0].op_str, NULL, 16);
//assert(dwdest != 0);
if (GE_X_LE(dwprevrva, dwdest, dwprevrva + i + insn[0].size) == FALSE && dwdest != 0)
{
bool everbeenbefore = false;
for (auto& fuck : rangelist)
{
if (GE_X_LE(fuck.startrva, dwdest, fuck.endrva))
{
everbeenbefore = true;
break;
}
}
for (auto& fuck : todorva)
{
if (dwdest == fuck)
{
everbeenbefore = true;
break;
}
}
if (everbeenbefore == false)
{
todorva.push_back(dwdest);
}
}
}
#pragma endregion
#pragma region β
//发现终点, 保存本块区域, 看是否有其他路径点未遍历
if (cs_insn_group(handle, insn, CS_GRP_RET) || insn[0].id == X86_INS_JMP)
{
range temp = { 0 };
temp.startrva = dwprevrva;
temp.endrva = dwprevrva + i + insn[0].size - 1;
temp.dwsize = i + insn[0].size;
rangelist.push_back(temp);
//将todorva中, 本块走过的rva全部删除
for (auto damn = todorva.begin(); damn != todorva.end(); )
{
if (GE_X_LE(dwprevrva, *damn, dwprevrva + i + insn[0].size - 1))
{
damn = todorva.erase(damn);
}
else
{
++damn;
}
}
if (todorva.empty())
{
//没有未遍历的了..
goto outofwhile;
}
else
{
nextrva = todorva.back();
todorva.pop_back();
goto outoffor;
}
}
#pragma endregion
i += insn[0].size;
cs_free(insn, count);
}
outoffor:
dwprevrva = nextrva;
}
cs_close(&handle);
outofwhile:
//开始合并rangelist
//先对rangelist按照startrva升序排列
if (rangelist.size() > 1)
{
std::sort(rangelist.begin(), rangelist.end(), comparer);
//因为已经排序过, 所以只需要判断相邻两个是否能合成即可
for (auto iter = rangelist.begin(); iter != rangelist.end() - 1;)
{
if (checkcommon(*iter, *(iter + 1)))
{
(*iter).startrva = min((*iter).startrva, (*(iter + 1)).startrva);
(*iter).endrva = max((*iter).endrva, (*(iter + 1)).endrva);
(*iter).dwsize = (*iter).endrva - (*iter).startrva + 1;
iter = rangelist.erase(iter + 1);
--iter;
}
else
{
++iter;
}
}
}
return 0;
} 我这代码对我当时研究的已经够用了, 你的可能得改改, 库用的capstone
|
能力值:
( LV13,RANK:270 )
|
-
-
19 楼
boursonjane
#define GE_X_LE(a,x,b) (((x)>=(a)) && ((x ... 好的,我好好研究一下,谢谢大佬。
最后于 2020-10-12 14:54
被baolongshou编辑
,原因:
|