📄 cfuncstep1.cpp
字号:
// Copyright(C) 1999-2005 LiuTaoTao,bookaa@rorsoft.com
#include "stdafx.h"
#include "CISC.H"
#include "cexe2c.h"
#include "CFuncStep1.h"
static void Add_in_order(EALIST *list, ea_t i)
{
if (list->IsEmpty())
{
list->AddHead(i);
return;
}
POSITION pos = list->GetHeadPosition();
while (pos)
{
POSITION savpos = pos;
ea_t ea = list->GetNext(pos);
if (ea == i)
return; // 已经有了,就算了
if (ea > i)
{
list->InsertBefore(savpos,i);
return;
}
}
list->AddTail(i);
}
void CFuncStep1::check_if_switch_case(ea_t cur_off, CaseList* pcaselist,EALIST* pjxxlist,
XCPUCODE* pxcpu)
{//static function
if (pxcpu->opcode != C_JMP)
return;
if (pxcpu->op[0].mode != OP_Address)
return;
if (pxcpu->op[0].addr.base_reg_index != _NOREG_)
return;
if (pxcpu->op[0].addr.off_reg_index == _NOREG_)
return;
if (pxcpu->op[0].addr.off_reg_scale != 4)
return;
if (pxcpu->op[0].addr.off_value <= 0x401000)
return;
//alert("switch case find 1");
//Code_SwitchCase1();
ea_t ptbl = pxcpu->op[0].addr.off_value;
//alert_prtf("table is %x",ptbl);
if (! IfInWorkSpace(ptbl))
return; // 确认这个table有效
//alert("switch case find 2");
ea_t d = Peek_D(ptbl);
if (! IfInWorkSpace(d))
return; // 确认第一条有效
//alert("switch case find 3");
ea_t break_off = 0; // 下面,要确定break_off的值
POSITION pos = pjxxlist->GetHeadPosition();
while (pos)
{
ea_t ea = pjxxlist->GetNext(pos);
if (ea > cur_off)
{
break_off = ea;
break;
}
}
if (break_off == 0)
return; // 没找到条件跳?不对劲
//alert("switch case find 4");
//if (pjxx->jmp.jmp_type != JMP_ja)
// return; // 不是ja,也不对
if (d < cur_off || d > break_off)
return; // 第一个就没对准,不行
//alert("switch case find 5");
//alert("rreally switch case");
CASE_t *pnew = new CASE_t;
pnew->jxx_opcode = cur_off;
pnew->caselist = new EALIST;
pcaselist->AddHead(pnew);
for (int i=0;;i++)
{
d = Peek_D(ptbl+i*4);
// if (! IfInWorkSpace(d))
if (d < cur_off || d > break_off)
break;
Add_in_order(pjxxlist,d);
pnew->caselist->AddTail(d);
}
}
static bool any_free_ea(EALIST *jxxlist, EALIST *usedlist, ea_t* pea)
{
POSITION pos = jxxlist->GetHeadPosition();
while (pos)
{
ea_t ea = jxxlist->GetNext(pos);
if (! usedlist->Find(ea))
{
*pea = ea;
return true;
}
}
return false;
}
void CFuncStep1::CheckIfJustSwitchCase(CaseList& caselist, ea_t ea)
{
POSITION pos1 = caselist.GetHeadPosition();
while (pos1)
{
CASE_t *p1 = caselist.GetNext(pos1);
if (p1->jxx_opcode == ea) // really
{ // now, add some jcase instruction
POSITION pos2 = p1->caselist->GetHeadPosition();
while (pos2)
{
ea_t case_ea = p1->caselist->GetNext(pos2);
assert(case_ea);
AsmCode *pnew = AsmCode::new_AsmCode();
pnew->linear = ea;
pnew->xcpu.opcode = C_JCASE;
pnew->xcpu.op[0].mode = OP_Near;
pnew->xcpu.op[0].nearptr.offset = case_ea;
this->m_asmlist->AddTail(pnew);
//alert("insert 1 C_JCAES");
}
break; // only one can be true
}
}
}
void CFuncStep1::CreateNewFunc_if_CallNear()
{
POSITION pos1 = m_asmlist->GetHeadPosition();
while (pos1)
{
AsmCode* pasm = m_asmlist->GetNext(pos1);
XCPUCODE* pxcpu = &pasm->xcpu;
if ( pxcpu->opcode == C_CALL && pxcpu->op[0].mode == OP_Near)
{
//log_prtl("find Call %x",xcpu.op[0].nearptr.offset);
g_Cexe2c->func_new(pxcpu->op[0].nearptr.offset);
}
}
}
bool CFuncStep1::Step_1(ea_t head_off)
// 找到函数结束地址,生成asm opcode list
{
//assert(m_nStep == 0);
CaseList caselist;
EALIST jxxlist;
EALIST usedlist;
ea_t ea = head_off;
assert(ea < 0x10000000);
assert(ea >= 0x400000);
jxxlist.AddHead(ea);
while (any_free_ea(&jxxlist,&usedlist,&ea))
{ // 走遍所有的jxx
for (;;)
{
Add_in_order(&usedlist,ea);
CDisasm the;
the.Disasm_OneCode(ea); //ea会递增的
if (the.get_xcpu()->IsJxx() || the.get_xcpu()->IsJmpNear())
{
Add_in_order(&jxxlist, the.get_xcpu()->op[0].nearptr.offset);
}
else
{
check_if_switch_case(ea,&caselist,&jxxlist, the.get_xcpu());
}
if (the.get_xcpu()->opcode == C_RET || the.get_xcpu()->opcode == C_JMP )
break;
if (usedlist.Find(ea))
break;
}
}
POSITION pos = usedlist.GetHeadPosition();
while (pos)
{ // 生成asm opcode list
if (this->m_asmlist == NULL)
{
this->m_asmlist = new AsmCodeList;
}
ea_t ea = usedlist.GetNext(pos);
AsmCode *p = AsmCode::new_AsmCode();
p->linear = ea;
CDisasm the;
p->opsize = the.Disasm_OneCode(ea);
p->xcpu = *the.get_xcpu();
this->m_asmlist->AddTail(p);
// 查找是不是刚过一个swith case
this->CheckIfJustSwitchCase(caselist, ea);
}
AsmCode *pasm = this->m_asmlist->GetTail();
m_end_off = pasm->linear + pasm->opsize;
return true;
}
//==========================================
static bool isLeave(AsmCode* p)
{ // 如果是leave或mov esp,??之类的指令,则当前stack状态对后面没有影响
if (p->xcpu.opcode == C_LEAVE)
return true;
if (p->xcpu.opcode == C_MOV
&& (p->xcpu.op[0].mode == OP_Register)
&& (p->xcpu.op[0].reg.reg_index == _ESP_) //mov esp,ebp
)
return true;
return false;
}
AsmCode* CFuncLL::ea2pasm(ea_t ea)
{
POSITION pos = m_asmlist->GetHeadPosition();
while (pos)
{
AsmCode* p = m_asmlist->GetNext(pos);
if (p->linear == ea)
return p;
}
assert_msg(0,"whye here");
return NULL;
}
bool CFuncLL::stack_stack(AsmCode* p0, AsmCode* p1)
{ // 只要干了任何一件有意义的事,就 return true
signed int & esp0 = p0->esp_level;
signed int & esp0_next = p0->esp_level_next;
signed int & esp1 = p1->esp_level;
// 首先,是p0自身的建设-------
if (isLeave(p0))
{ //p0自身的esp和esp_next无关的情况
if (esp0_next == ESP_UNKNOWN)
{
signed int esp = ESP_UNKNOWN;
if (Asm_Code_Change_ESP(esp, &p0->xcpu))
{
esp0_next = esp;
return true;
}
}
}
else
{
if (esp0_next == ESP_UNKNOWN)
{
if (p0->xcpu.opcode == C_JMP || p0->xcpu.opcode == C_RET)
{
esp0_next = ESP_IGNORE;
return true;
}
if (esp0 != ESP_UNKNOWN)
{
signed int esp = esp0;
if ( Asm_Code_Change_ESP(esp, &p0->xcpu) )
{
esp0_next = esp;
return true;
}
}
}
if (esp0_next != ESP_UNKNOWN
&& (esp0_next != ESP_IGNORE)
&& (esp0 == ESP_UNKNOWN)
) // 反查
{
signed int esp = 0;
if ( Asm_Code_Change_ESP(esp, &p0->xcpu) )
{
//esp0_next = esp0 + esp;
esp0 = esp0_next - esp;
return true;
}
}
if (esp0 != ESP_UNKNOWN
&& esp0_next != ESP_UNKNOWN
&& p0->xcpu.opcode == C_CALL
&& p0->xcpu.op[0].mode == OP_Address
&& p0->xcpu.op[0].addr.base_reg_index == _NOREG_
&& p0->xcpu.op[0].addr.off_reg_index == _NOREG_
)
{
ea_t address = p0->xcpu.op[0].addr.off_value;
CApi *papi = g_ApiManage->get_api(address); //find it
if (papi)
{
if (esp0_next != esp0 + papi->m_stack_purge)
return false; //find error
}
else
{ //not find, insert it
alert_prtf("error not find api %x", address);
g_ApiManage->new_api(address,esp0_next - esp0);
return true;
}
}
}
// Jmp -------------------------
if (p1->xcpu.IsJxx() || p1->xcpu.IsJmpNear())
{
ea_t jmpto = p1->xcpu.op[0].nearptr.offset;
AsmCode* p = ea2pasm(jmpto);
if (p->esp_level == ESP_UNKNOWN && esp1 != ESP_UNKNOWN)
{
p->esp_level = esp1;
return true;
}
if (p->esp_level != ESP_UNKNOWN && esp1 == ESP_UNKNOWN)
{
esp1 = p->esp_level;
return true;
}
if (p->esp_level != ESP_UNKNOWN && esp1 != ESP_UNKNOWN)
{
if (p->esp_level != esp1)
return false;
}
}
// -----------------------------------
if (p1->xcpu.opcode == C_RET)
{
if (esp1 == ESP_UNKNOWN)
{
esp1 = 0;
return true;
}
if (esp1 != 0)
return false;
}
// -----------------------------------
if (esp0_next == ESP_UNKNOWN && esp1 != ESP_UNKNOWN)
{
esp0_next = esp1;
return true;
}
if (esp0_next != ESP_UNKNOWN
&& esp0_next != ESP_IGNORE
&& esp1 == ESP_UNKNOWN)
{
esp1 = esp0_next;
return true;
}
if (esp0_next != ESP_UNKNOWN
&& esp0_next != ESP_IGNORE
&& esp1 != ESP_UNKNOWN)
{ //do some check
if (esp0_next != esp1)
return false;
}
return false;
}
ea_t FindApiAddress_Reg(DWORD regindex, XCPUCODE* pxcpu1, AsmCodeList* asmlist)
{
//意思是,我要正确处理call eax
//到前面去找一个mov eax, [405070]
ea_t retn = 7;
POSITION pos = asmlist->GetHeadPosition();
while (pos)
{
AsmCode* p = asmlist->GetNext(pos);
XCPUCODE* pxcpu = &p->xcpu;
if (pxcpu == pxcpu1)
return retn;
if (pxcpu->opcode == C_MOV
&& pxcpu->op[0].mode == OP_Register
&& pxcpu->op[0].reg.reg_index == regindex)
{
if (pxcpu->op[1].mode == OP_Address
&& pxcpu->op[1].addr.base_reg_index == _NOREG_
&& pxcpu->op[1].addr.off_reg_index == _NOREG_
) //call [405070]
{
ea_t address = pxcpu->op[1].addr.off_value;
retn = address;
}
}
}
return retn;
}
bool CFuncLL::Asm_Code_Change_ESP(int &esp, XCPUCODE* pxcpu)
{//算出来esp,就return true
// 让我们假定一个func中只出现一次mov ebp,esp
if (pxcpu->opcode == C_MOV
&& (pxcpu->op[0].mode == OP_Register)
&& (pxcpu->op[0].reg.reg_index == _ESP_)
&& (pxcpu->op[1].mode == OP_Register)
&& (pxcpu->op[1].reg.reg_index == _EBP_))
{
if (this->m_EBP_base != Not_EBP_based
&& esp == ESP_UNKNOWN)
{
esp = this->m_EBP_base; //mov esp,ebp
return true;
}
}
if (pxcpu->opcode == C_MOV
&& (pxcpu->op[0].mode == OP_Register)
&& (pxcpu->op[0].reg.reg_index == _EBP_)
&& (pxcpu->op[1].mode == OP_Register)
&& (pxcpu->op[1].reg.reg_index == _ESP_))
{
if (esp != ESP_UNKNOWN
&& this->m_EBP_base == Not_EBP_based)
{
this->m_EBP_base = esp; //mov ebp,esp
return true;
}
}
if (pxcpu->opcode == C_LEAVE)
{
esp = m_EBP_base; // mov esp,ebp
esp += 4; // pop ebp
}
if (pxcpu->opcode == C_PUSH)
esp -= 4;
if (pxcpu->opcode == C_POP)
esp += 4;
if (pxcpu->opcode == C_SUB)
if (pxcpu->op[0].mode == OP_Register)
if (pxcpu->op[0].reg.reg_index == _ESP_)
if (pxcpu->op[1].mode == OP_Immed)
{
esp -= pxcpu->op[1].immed.immed_value;
}
if (pxcpu->opcode == C_ADD)
if (pxcpu->op[0].mode == OP_Register)
if (pxcpu->op[0].reg.reg_index == _ESP_)
if (pxcpu->op[1].mode == OP_Immed)
{
esp += pxcpu->op[1].immed.immed_value;
}
if (pxcpu->opcode == C_CALL)
{
if (pxcpu->op[0].mode == OP_Near)
{
CFunc* pfunc = g_Cexe2c->GetFunc(pxcpu->op[0].nearptr.offset);
if (pfunc == NULL)
return false;
if (pfunc->m_IfLibFunc)
{
//esp += pfunc->m_stack_purge;
assert(pfunc->m_functype);
esp += pfunc->m_functype->get_stack_purge();
return true;
}
if (pfunc->m_nStep < STEP_IDA_1)
return false;
esp += pfunc->m_stack_purge;
return true;
}
if (pxcpu->opcode == C_CALL &&
pxcpu->op[0].mode == OP_Address &&
pxcpu->op[0].addr.base_reg_index == _NOREG_ &&
pxcpu->op[0].addr.off_reg_index == _NOREG_
) //call [405070]
{
ea_t address = pxcpu->op[0].addr.off_value;
CApi* papi = g_ApiManage->get_api(address);//,stacksub)) //find it
if (papi)
{
esp += papi->m_stack_purge;
return true;
}
}
if (pxcpu->opcode == C_CALL &&
pxcpu->op[0].mode == OP_Register
) //call eax
{
ea_t address = FindApiAddress_Reg(pxcpu->op[0].reg.reg_index, pxcpu, this->m_asmlist);
CApi* papi = g_ApiManage->get_api(address);//,stacksub)) //find it
if (papi)
{
esp += papi->m_stack_purge;
return true;
}
}
return false;
}
if (esp == ESP_UNKNOWN)
return false;
return true;
// 影响stack的有这几种情况:
// enter leave
// push ebp,mov ebp,esp,.....,mov esp,ebp,pop ebp
// push,pop
// call near
// ret时检查是否已平衡
// 对call [immed]等,暂不考虑s
}
void CFuncLL::AddRemoveSomeInstr()
{
POSITION pos = m_asmlist->GetHeadPosition();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -