|
|
|
|
|
[原创]调试器中不通过TF标记位实现单步操作的实现思路
难得今天上网,发现没有人讨论~ 反而钱老师给了一个精华~ 为了对得起这个精华,我就顺便贴下我的实现代码和效果图吧~(代码太挫……) 关于代码的分离部分: //************************************************************************ // 函数名: Lex_Split // 权 限: public // 返回值: list<TCHAR*>* 返回一个字符串链表 // 参 数: IN TCHAR * pszRegular // 参 数: IN TCHAR * pszSource // 说 明: 从指定的字符串中分离出各种子串 // 合 格: //************************************************************************ list<TCHAR*>* Lex_Split(IN const TCHAR* pszRegular, IN const TCHAR* pszSource) { int ntmpLen = 0; int nCount = 0; // 用来统计匹配的数量作为返回值 match_results result; // 匹配结果 list<TCHAR*> *pszResultList = new list<TCHAR*>; REGEX_FLAGS emRegEx*** = GLOBAL | ALLBACKREFS | NOCASE | SINGLELINE; rpattern pat((LPCTSTR)pszRegular, emRegEx***); //正则模式及设置 int iGroups = pat.cgroups(); match_results::backref_type br = pat.match(pszSource, result ); if (pszRegular == NULL || pszSource == NULL || br.matched == FALSE) { return NULL; } for( int i=0; i < result.cbackrefs(); i++ ) { ntmpLen = _tcslen(result.backref(i).str().c_str()); if( i%iGroups == 0 && ntmpLen > 0) { nCount++; TCHAR *pszResult = new TCHAR[ntmpLen+1]; ZeroMemory(pszResult, ntmpLen+1); _tcscpy(pszResult, result.backref(i).str().c_str()); pszResultList->push_back(pszResult); } } return pszResultList; } 关于根据token获取值的部分: //************************************************************************ // 函数名: GetRegTokenValue // 权 限: public // 返回值: DWORD // 参 数: IN CONTEXT * tagpContext // 参 数: TCHAR * pszRegToken // 说 明: 获取 分离出的各种token代表的值 // 合 格: //************************************************************************ DWORD GetRegTokenValue(IN CONTEXT *tagpContext, TCHAR *pszRegToken) { for (int i = 0; i < 8; i++) { if (_tcsicmp(st_RegInfo[i].pszString, pszRegToken) != 0) { continue; } switch(st_RegInfo[i].tagType.e) { case REG_TYPE::REG_TYPE_EAX: return tagpContext->Eax; case REG_TYPE::REG_TYPE_EBX: return tagpContext->Ebx; case REG_TYPE::REG_TYPE_ECX: return tagpContext->Ecx; case REG_TYPE::REG_TYPE_EDX: return tagpContext->Edx; case REG_TYPE::REG_TYPE_ESP: return tagpContext->Esp; case REG_TYPE::REG_TYPE_EBP: return tagpContext->Ebp; case REG_TYPE::REG_TYPE_ESI: return tagpContext->Esi; case REG_TYPE::REG_TYPE_EDI: return tagpContext->Edi; default: ; } } return -1; } //************************************************************************ // 函数名: GetRegTokenValue // 权 限: public // 返回值: DWORD // 参 数: TCHAR * pszCstToken // 说 明: 获取 分离出的 常量 的值 // 合 格: //************************************************************************ DWORD GetCstTokenValue(TCHAR *pszCstToken) { DWORD dwResult = 0; if (pszCstToken == NULL) { return 0; } _stscanf(pszCstToken, _T("%x"), &dwResult); return dwResult; } 整体上的模拟运算的流程如下: //************************************************************************ // 函数名: CalcSimulator // 权 限: public // 返回值: DWORD // 参 数: IN CONTEXT * tagpContext // 参 数: IN list<TCHAR * > * pTokenList // 说 明: 表达式计算 // 合 格: //************************************************************************ DWORD CalcSimulator(IN CONTEXT *tagpContext, IN list<TCHAR*>* pTokenList) { int nCount = 0; DWORD dwResult = 0; // 前一个操作数 DWORD dwCurNum = 0; if (tagpContext == NULL || pTokenList == NULL) { return -1; } if (pTokenList->size() <= 1) { return -1; } OPERATE_STATE em_OperReg; OPERATE_STATE em_OperCst; OPERATE_STATE em_OperSign; OPERATE_STATE em_OperStart; OPERATE_STATE em_OperEnd; em_OperReg.e = OPERATE_STATE::STATE_OPER_REG; em_OperCst.e = OPERATE_STATE::STATE_CONST_NUM; em_OperSign.e = OPERATE_STATE::STATE_SIGN_TOKEN; em_OperStart.e= OPERATE_STATE::STATE_SIGN_START; em_OperEnd.e = OPERATE_STATE::STATE_SIGN_END; pTokenList = CalcMulti(tagpContext, pTokenList); // 先处理乘法 if (pTokenList == (list<TCHAR*>*)-1) { return -1; } nCount = pTokenList->size(); list<TCHAR*>::iterator it = pTokenList->begin(); for ( int i = 0 ; i < nCount ; i++ ) { TCHAR *pResultBuf = NULL; pResultBuf = *it; if (pResultBuf == NULL) { continue; } if (Is(em_OperStart, pResultBuf)) { // 清空栈内容 while (!g_WaitForCalcStack.empty()) { g_WaitForCalcStack.pop(); } } if (Is(em_OperEnd, pResultBuf)) { // 处理完成,开始计算栈中的数据 int nSize = g_WaitForCalcStack.size(); for (int i = 0; i < nSize; i ++) { dwResult += g_WaitForCalcStack.top(); g_WaitForCalcStack.pop(); } break; } if (Is(em_OperReg, pResultBuf)) { // 如果是寄存器,就保存寄存器中的内容 g_WaitForCalcStack.push(GetRegTokenValue(tagpContext, pResultBuf)); } if (Is(em_OperCst, pResultBuf)) { // 如果是立即数,就保存其值 g_WaitForCalcStack.push(GetCstTokenValue(pResultBuf)); } if (Is(em_OperSign, pResultBuf)) { if (_tcsicmp(pResultBuf, _T("-")) == 0) { it++; //如果是减法,则需要将后面的数据取补保存 pResultBuf = *it; if (Is(em_OperReg, pResultBuf)) { // 如果是寄存器,就保存寄存器中的内容 dwCurNum = GetRegTokenValue(tagpContext, pResultBuf); g_WaitForCalcStack.push(dwCurNum); } if (Is(em_OperCst, pResultBuf)) { // 如果是立即数,就保存其值 dwCurNum = GetCstTokenValue(pResultBuf); dwCurNum = (~dwCurNum)+1; // 求补码 g_WaitForCalcStack.push(dwCurNum); } } } it++; } return dwResult; 由于乘法在我们当前的环境下优先级最高,所以我将乘法的计算过程分离出去了: // 先计算乘法 static list<TCHAR*>* CalcMulti(IN CONTEXT *tagpContext, IN list<TCHAR*>* pTokenList) { if (tagpContext == NULL || pTokenList == NULL) { return NULL; } TCHAR *pPreToken = NULL; TCHAR *pResultBuf = NULL; DWORD dwPreNum = 0; // 前一个操作数 DWORD dwNextNum = 0; // 后一个操作数 int nCount = 0; OPERATE_STATE em_OperReg; OPERATE_STATE em_OperCst; OPERATE_STATE em_OperSign; OPERATE_STATE em_OperStart; OPERATE_STATE em_OperEnd; em_OperReg.e = OPERATE_STATE::STATE_OPER_REG; em_OperCst.e = OPERATE_STATE::STATE_CONST_NUM; em_OperSign.e = OPERATE_STATE::STATE_SIGN_TOKEN; em_OperStart.e= OPERATE_STATE::STATE_SIGN_START; em_OperEnd.e = OPERATE_STATE::STATE_SIGN_END; list<TCHAR*>* pResultList = new list<TCHAR*>; list<TCHAR*>::iterator it = pTokenList->begin(); nCount = pTokenList->size(); for ( int i = 0 ; i < nCount; i++ ) // 多循环了一次,需要看看 { pResultBuf = *it; if (pResultBuf == NULL) { continue; } if (_tcsicmp(pResultBuf, _T("*")) != 0) { pResultList->push_back(pResultBuf); } if (i > 0) { it--; pPreToken = *it; it++; } if (pPreToken != NULL && _tcsicmp(pPreToken, _T("*")) == 0) { // 如果前一个是*也不保存当前的 pResultList->pop_back(); } if (Is(em_OperSign, pResultBuf) && _tcsicmp(pResultBuf, _T("*")) == 0) { pResultList->pop_back(); // 先取出前一个操作数 it--; pResultBuf = *it; if (Is(em_OperReg, pResultBuf)) { // 如果是寄存器,就保存寄存器中的内容 dwPreNum = GetRegTokenValue(tagpContext, pResultBuf); } if (Is(em_OperCst, pResultBuf)) { // 如果是立即数,就保存其值 dwPreNum = GetCstTokenValue(pResultBuf); } // 取出后一个操作数 it++; it++; pResultBuf = *it; if (Is(em_OperReg, pResultBuf)) { // 如果是寄存器,就保存寄存器中的内容 dwNextNum = GetRegTokenValue(tagpContext, pResultBuf); } if (Is(em_OperCst, pResultBuf)) { // 如果是立即数,就保存其值 dwNextNum = GetCstTokenValue(pResultBuf); } TCHAR* pNewNum = new TCHAR[4]; ZeroMemory(pNewNum, sizeof(TCHAR)*4); _stprintf(pNewNum, _T("%d"), dwPreNum*dwNextNum); pResultList->push_back(pNewNum); it--; } it++; } pTokenList->clear(); if (pTokenList) { delete pTokenList; pTokenList = NULL; } pTokenList = pResultList; return pResultList; } 主要的代码就这些了,也用不着我多说废话了,下面贴一下效果图: 先贴个简单的立即数寻址的: CALL reg形式的: 再看下 call [addr]这种形式的: 再看下return的效果: 最后来个超级复杂的那种(我自己修改代码构造的测试程序): 就到这里吧,希望各位师兄能多提点意见,也希望本文能对其它朋友有所帮助。 |
|
|
|
|
|
有没有恢复IDT的软件
比如,一些修改的OD中的TOOL目录下,就有... |
|
|
|
[讨论]看雪论坛主题T恤
为啥要15贴啊, 难道你想?? 我觉得, 论坛精华够15贴的人太多了, 再少也得20个精华的才可以. 这样一来可以体现 T-shirt 的价值, 再就是也可以让 各位大牛再发几个精华~~~ 泉哥, 再分享3个精华撒~~ |
|
[讨论]看雪论坛主题T恤
恩, 这个问题, 前一段时间, 在加解密三群里讨论过, 由于我好几天没上网,不知道这事儿敲定了没有~~~ 我想, 这个问题, kanxue 老大也一定在筹备阶段了, 嘿嘿, 大家想一起去了~~~ |
操作理由
RANk
{{ user_info.golds == '' ? 0 : user_info.golds }}
雪币
{{ experience }}
课程经验
{{ score }}
学习收益
{{study_duration_fmt}}
学习时长
基本信息
荣誉称号:
{{ honorary_title }}
能力排名:
No.{{ rank_num }}
等 级:
LV{{ rank_lv-100 }}
活跃值:
在线值:
浏览人数:{{ visits }}
最近活跃:{{ last_active_time }}
注册时间:{{ user_info.create_date_jsonfmt }}
勋章
兑换勋章
证书
证书查询 >
能力值