首页
论坛
课程
招聘
[OllyDbg 1.x] [分享]C语言脚本_for_ollydbg1.1.rar(更新)
2014-9-30 16:19 5873

[OllyDbg 1.x] [分享]C语言脚本_for_ollydbg1.1.rar(更新)

2014-9-30 16:19
5873
//tcc script脚本编写例子------单步机
//目标程序来自某个视频教程的第一讲,是个加了UPX压缩壳的exe文件,可以试着加载下面的脚本代码,找到该程序的OEP

#include "D:\Tools\OllyICE\plugin\C_Script_Data\type.h"

//申明外部符号
extern HWND h_script_frame;//外部变量,使用前需要申明
extern void _stdcall Sleep(int);//外部函数,使用前必须申明
extern int _stdcall MessageBoxA(HWND,char*,char*,int);//同上

#define D_CALL_OFFSET_LIMIT 20//界定值,以此判断到底是远CALL还是近CALL

typedef unsigned long u_int32;

char *s_heap_str;//buffer,需要时存放字符串,实际上,后面并没有用上
char *s_heap_cmd;//buffer,需要时存放字符串,这个倒是用上了

#define tsa_abs(A) ((A)>0?(A):-(A))//求绝对值

void int3_insert(unsigned long u_addr)
{
        _Setbreakpoint(u_addr,TY_ACTIVE,0);
}

void int3_remove(unsigned long u_addr)
{
        _Deletebreakpoints(u_addr,u_addr+1,0);
}

void step_over()
{
        _Go(0,0,STEP_OVER,1,1);
}

void step_in()
{
        _Go(0,0,STEP_IN,1,1);
}

void run()
{
        _Go(0,0,STEP_RUN,1,1);
}

void run_to(unsigned long u_addr)
{
        _Tempbreakpoint(u_addr,TY_ONESHOT|TY_KEEPCOND); run();
}

void run_to_shortcut(unsigned long u_addr)
{
        _Sendshortcut(PM_DISASM,u_addr,0x100,0,0,0x73);
}

int disasm_string(unsigned long u_addr,t_disasm *p_da)
{
        char *s_cmd=(char*)malloc(128);

        if(0==_Readcommand(u_addr,s_cmd))
        {
                free(s_cmd); return 0;
        }

        int i_byte=_Disasm(s_cmd,128,u_addr,0,p_da,DISASM_ALL,_Getcputhreadid());

        free(s_cmd); return i_byte;
}

//先判断一条指令是不是跳转指令,然后再判断该指令是往前跳还是往后跳
//[往回跳,返回-1] [往前跳,返回1] [不是跳转指令,返回0]
int jump_type(unsigned long u_addr,t_disasm *p_dis)
{
        unsigned long u_cmd_type=p_dis->cmdtype;
        if((C_JMP==u_cmd_type) || ((C_JMC==u_cmd_type) && (1==p_dis->condition)))
        {
                unsigned long u_jmp_addr=p_dis->jmpaddr; if(u_jmp_addr>u_addr) return 1; return -1;
        }
        return 0;
}

//先判断一条指令是不是函数调用,然后再判断该指令近call还是远call
//[近call,返回-1] [远call,返回1] [非call,返回0]
int call_type(unsigned long u_addr,t_disasm *p_dis)
{
        unsigned long u_cmd_type=p_dis->cmdtype;
        unsigned long u_jmp_addr=p_dis->jmpaddr;
        if(C_CAL==u_cmd_type)
        {
                if(tsa_abs(u_jmp_addr-u_addr)>D_CALL_OFFSET_LIMIT) return 1; return -1;
        }
        return 0;
}

//处理特殊情况
int extra_handle(unsigned long u_addr,t_disasm *p_dis)
{
        if(0x5791E6==u_addr)//第一次跑飞的地址
        {
                run_to(0x5791EE); return 1;
        }
        else if(0x5791EF==u_addr)//第二次跑飞的地址
        {
                step_over(); return 1;
        }
        else if(0x47738C==u_addr)//OEP
        {
                MessageBoxA(h_script_frame,"到达OEP,请卸载脚本,以免影响调试","提示:",0); return 1;
        }
        return 0;
}


void on_code_insert()//当脚本被载入ollydbg进程的时候,on_code_insert将会被调用一次
{
        s_heap_str=(char*)malloc(TEXTLEN);
        s_heap_cmd=(char*)malloc(MAXCMDSIZE);

        step_in();
}

void on_code_delete()//当脚本被卸载时,on_code_delete会被调用一次
{
        free(s_heap_str);
        free(s_heap_cmd);
}

//每当OD断下目标进程的时候,on_pausedex都会被调用(OD插件开发文档里是这么说的)
int on_pausedex(int reason,int dummy,t_reg *reg,DEBUG_EVENT *debugevent)
{
//        Sleep(500);//让OD跑慢一点,便于观察,可以直接注释掉

        u_int32 u_eip=reg->ip; t_disasm t_dis;

        int i_cmd_len=disasm_string(u_eip,&t_dis);
        if(0==i_cmd_len)
        {
                tsa_print(8,"无法解析当前指令,本次执行终止\n"); return 0;
        }

        if(extra_handle(u_eip,&t_dis)!=0) return 0;

        if((-1)==jump_type(u_eip,&t_dis))
        {
                u_int32 u_next=u_eip+i_cmd_len;

                tsa_print(11,"[eip:0x%0X]回跳,前往:0x%0X\n",u_eip,u_next);

                run_to(u_next); return 0;
        }
        else if((-1)==call_type(u_eip,&t_dis))
        {
                tsa_print(17,"[eip:0x%0X]近CALL,步入\n",u_eip); step_in(); return 0;
        }
        step_over(); return 0;
}

--------------------------------------------------------------------------------------------------------------
2014/10/15
之前的界面有点太寒碜了,于是更新一下,网上找了一个封装DLL,支持一下语法高亮,就算是1.3版本吧
---------------------------------------------------------------------------------------------------------------
修正了一些问题。

还是把C_Script_Data和tcc_script.dll解压到OD的plugin目录。

第五届安全开发者峰会(SDC 2021)议题征集正式开启!

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (9)
雪    币: 7
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xiaoming 活跃值 2014-9-30 16:20
2
0
晕了,为嘛编辑帖子需要5Kx?现金在不知不觉间就米有了,why?
-------------------------------------------------------------------------------------------------------------------------------
tcc script for ollydbg1.1 以下简称 TS
-------------------------------------------------------------------------------------------------------------------------------
1.TS使用要求:会使用OD,并懂一点C语言基础知识即可

2.TS可以满足哪些需求?
     (1)基本上,编写TS脚本,可以省去一些额外的手工调试劳动
     (2)如果有编写插件的需要,可以用TS测试某些代码模块
     (3)提供类似OllyScript的功能

3.在Symbol.ini中为TS添加符号支持(系统API,OD API,模块导出变量,任意地址)
[init]
count=101
   .
   .
   .
[100]
module=符号所在模块,比如:user32.dll 或 NULL(NULL表示宿主进程,一般是ollydbg)
type=符号类型 调用约定,比如:int _stdcall
symbol=符号名,比如:MessageBoxA
addr=地址,一般为0
param=参数总字节数,比如:32位系统下,MessageBoxA参数总共16个字节,那么这里就是 16
open=是否立即使用,比如:1就是立即使用

----------除了函数以外,也可以用类似方法引入变量,不过OD1.1好像没有导出变量
----------需要详细说明的键名是addr
----------假如OD主进程或者某个插件模块中,存在某个地址0x45001280,这是个很有用函数的入口地址,但这个函数没有导出.那么这时,就可以这样设置addr键值:addr=0x45001280
----------同样的,如果0x45001280是个变量,也可以设置addr=0x45001280,以便在TS中使用这个变量

4.在TS脚本编写中,使用引入符号,比如:MessageBoxA
MessageBoxA是外部符号,它的实现在user32.dll中,TS只能得到它的入口地址,至于它的调用约定,参数列表则无法得知.所以在调用它之前,必须先申明其原型

extern int MessageBoxA(HWND,char*,char*,int);

另外,对于引入的变量符号,使用之前也要申明原型.不过对于_cdecl函数,可以无需申明直接使用,因为_cdecl是TS默认的调用约定,直接使用不会导致堆栈出问题

5.TS如何跟ollydbg交互
ollydbg在实行某些调试动作的时候,会主动调用一些外部功能,比如:on_pausedex就是ollydbg遇上断点时必定会调用的一个外部函数。那么可以在编写TS脚本的时候,实现这个函数,提供给ollydbg调用。在od_msg.cpp中描述了这类函数的原型

6.一些函数原型(windows api 和 ollydbg api 不多介绍,这里只说一下TS提供的api)
void tsa_error(char *fmt,...);//显示一个消息框
void tsa_print(int i_color,char *fmt,...);//在TS输出窗口显示信息
void tsa_libray_insert(HANDLE h_process,char *c_libray);//远程插入DLL

7.将tcc_script.dll插入到目标进程(理论上,tcc_script.dll是可以被插入到被调试进程,做一些patch工作的,但我没试过)
void on_code_insert()
{
        tsa_libray_insert(h_dest_proc,"......tcc_script.dll");
}

8.一楼是TS脚本编写的例子
雪    币: 4476
活跃值: 活跃值 (259)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
menglv 活跃值 2014-9-30 22:55
3
0
主要是要多些实例和使用说明,毕竟是一个新插件。
雪    币: 3476
活跃值: 活跃值 (351)
能力值: ( LV9,RANK:175 )
在线值:
发帖
回帖
粉丝
蚯蚓降龙 活跃值 2014-10-1 13:18
4
0
有什么用的...新手表示不懂...
雪    币: 7
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xiaoming 活跃值 2014-10-11 13:45
5
0
写脚本用的
雪    币: 27
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
寂寞寒烟 活跃值 2014-11-16 07:29
6
0
#include "D:\破解工具箱\动态调试\ODko\OD\plugin\C_Script_Data\type.h"
extern int _stdcall MessageBoxA(HWND,char*,char*,int);//同上
extern void _stdcall OutputDebugStringA(char*);
#define  DWORD unsigned long
#define  WORD unsigned short
#define  BYTE unsigned char

//条件断点类型: 硬件写断点
#define  CONDITION_BP_TYPE_H_W ((HB_WRITE        <<16)|PP_HWBREAK)
//条件断点类型: 硬件访问断点
#define  CONDITION_BP_TYPE_H_RW ((HB_ACCESS        <<16)|PP_HWBREAK)

#define false 0
#define true 1

//条件断点类型: 内存写断点
#define  CONDITION_BP_TYPE_M_W ((MEMBP_WRITE<<16)|PP_MEMBREAK)
//条件断点类型: 内存访问断点
#define  CONDITION_BP_TYPE_M_RW (((MEMBP_WRITE|MEMBP_READ)<<16)|PP_MEMBREAK)
typedef struct CDealer
{
        unsigned long m_dwBPAddr;
        unsigned long m_dwBPType;
        unsigned long m_dwBPSize;
        char* m_pConditinStr;       
} CDealer,*PCDealer;
typedef BYTE bool;
void __chkstk()
{

}
void step_over()
{
        _Go(0,0,STEP_OVER,1,1);
}

void step_in()
{
        _Go(0,0,STEP_IN,1,1);
}

void run()
{
        _Go(0,0,STEP_RUN,1,1);
}

void run_to(unsigned long u_addr)
{
        _Tempbreakpoint(u_addr,TY_ONESHOT|TY_KEEPCOND); run();
}

void run_to_shortcut(unsigned long u_addr)
{
        _Sendshortcut(PM_DISASM,u_addr,0x100,0,0,0x73);
}
BYTE Do(int reason, int extdata, t_reg *reg, DEBUG_EVENT* debugevent, CDealer* pDelaer)//是否处理了断点
{
        DWORD dwDr6;
        DWORD dwDr7;
        DWORD dwDrIndewX=0;
        DWORD dwRWXBitIndex=0;
        DWORD dwLenXBitIndex=0;
        DWORD dwDrX=0;
        DWORD dwRW=0;
        DWORD dwLen=0;
        int nExpressionRet=0;
        t_result expressionResult={0};

        if(reason==PP_HWBREAK)
        {
                run();
                dwDr6 = reg->dr6;
                dwDr7 = reg->dr7;
                if (dwDr6==0)
                {
                        OutputDebugStringA("dr6==0");
                }
                if (dwDr6&1)//如果是第1个寄存器的硬断
                {
                        dwDrIndewX=0;
OutputDebugStringA("dr0");
                }
                else if (dwDr6&(1<<1))//第二个
                {
                        dwDrIndewX=1;
OutputDebugStringA("dr1");
                }else if(dwDr6&(1<<2))//第三个
                {
                        dwDrIndewX=2;
OutputDebugStringA("dr2");
                }else if (dwDr6&(1<<3))
                {
                        dwDrIndewX=3;
OutputDebugStringA("dr3");
                }
                dwRWXBitIndex=16+dwRWXBitIndex*4;
                dwLenXBitIndex=18+dwRWXBitIndex*4;
                dwRW=(3<<dwRWXBitIndex)&(dwDr7);
                dwLen=(3<<dwLenXBitIndex)&dwDr7;
                dwDrX = reg->drlin[dwDrIndewX];
                if (dwRW==0)//表示是执行硬件断点
                {
                        return false;
                }
                OutputDebugStringA("sssqqqqqqqqqqq");
                if (dwRW==1)//写硬件断点
                {
                        if (pDelaer->m_dwBPType==CONDITION_BP_TYPE_H_W)
                        {
                                if (pDelaer->m_dwBPAddr==dwDrX)
                                {
                                        nExpressionRet=_Expression(&expressionResult,pDelaer->m_pConditinStr,0,0,0,pDelaer->m_dwBPAddr,pDelaer->m_dwBPSize,_Getcputhreadid());
                                        if (expressionResult.u)
                                        {
                                                return false;
                                        }else
                                        {
                                                run();
                                                return true;
                                        }
                                }
                        }
                        return false;                                                               
                }
                else //读或者写导致断下来
                {
                        if (pDelaer->m_dwBPType==CONDITION_BP_TYPE_H_RW)
                        {
                                if (pDelaer->m_dwBPAddr==dwDrX)
                                {
                                        nExpressionRet=_Expression(&expressionResult,pDelaer->m_pConditinStr,0,0,0,pDelaer->m_dwBPAddr,pDelaer->m_dwBPSize,_Getcputhreadid());
                                        if (expressionResult.u)
                                        {
                                                return false;
                                        }else
                                        {
                                                run();
                                                return true;
                                        }
                                }
                                return false;
                        }
                        return false;                                               
                }

        }else if (reason==PP_MEMBREAK)
        {
                return false;
        }                               
}

CDealer  g_dealerArr[5]={0};
//设置条件断点
void SetConditionBP(DWORD dwAddr,DWORD dwBPType,DWORD dwSize,char*pConditionStr)
{       
        CDealer* pDealer=0;
        DWORD i=0;
        for (;i<sizeof(g_dealerArr)/sizeof(g_dealerArr[0]);i++)
        {
                pDealer = &g_dealerArr[i];
                if (pDealer->m_pConditinStr==0)
                {
                        pDealer->m_dwBPAddr=dwAddr;
                        pDealer->m_dwBPSize=dwSize;
                        pDealer->m_dwBPType=dwBPType;
                        pDealer->m_pConditinStr=(char*)malloc(strlen(pConditionStr)+1);
                        strcpy(pDealer->m_pConditinStr,pConditionStr);
                        _Sethardwarebreakpoint(dwAddr,dwSize,dwBPType>>16);
                        return ;
                }
        }       
}
void DelConditionBP(DWORD dwAddr)
{
        CDealer* pDealer=0;
        DWORD i=0;
        for (;i<sizeof(g_dealerArr)/sizeof(g_dealerArr[0]);i++)
        {
                pDealer = &g_dealerArr[i];
                if (pDealer->m_dwBPAddr==dwAddr)
                {
                        free(pDealer->m_pConditinStr);
                        _Deletehardwarebreakbyaddr(pDealer->m_dwBPAddr);
                        pDealer->m_dwBPAddr=0;
                        pDealer->m_dwBPSize=0;
                        pDealer->m_dwBPType=0;
                        pDealer->m_pConditinStr=0;
                        _Deletehardwarebreakbyaddr(pDealer->m_dwBPAddr);
                        return;
                }
        }
}
int on_pausedex(int reason, int extdata, t_reg *reg, DEBUG_EVENT *debugevent)
{
        DWORD dw1;
        CDealer* pDealer=0;
        bool bDo=false;
        DWORD i;
       
        for ( i=0;i<sizeof(g_dealerArr)/sizeof(g_dealerArr[0]);i++)
        {
                pDealer = &g_dealerArr[i];
                if (pDealer->m_pConditinStr==0)
                {
                        continue;
                }
               
                bDo = Do(reason,extdata,reg,debugevent,pDealer);
                if (bDo)
                {
                        return true;
                }
        }
        return false;
}
void on_code_insert()//当脚本被载入ollydbg进程的时候,on_code_insert将会被调用一次
{
       
        SetConditionBP(0x13C9E6EC,CONDITION_BP_TYPE_H_W,4,"[[18CB80C]+24]!=0");
}

void on_code_delete()//当脚本被卸载时,on_code_delete会被调用一次
{
        CDealer* pDealer=0;
        DWORD i=0;
        for (;i<sizeof(g_dealerArr)/sizeof(g_dealerArr[0]);i++)
        {
                pDealer =& g_dealerArr[i];
                if (pDealer->m_pConditinStr)
                {
                        DelConditionBP(pDealer->m_dwBPAddr);
                }
        }
        run();
}
雪    币: 27
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
寂寞寒烟 活跃值 2014-11-16 07:31
7
0
楼主,这你看看,这int ODBG_Pausedex(int reason, int extdata, t_reg *reg, DEBUG_EVENT *debugevent);
这个回调到里面的  reg参数得到的dr6 为什么会是0呢
雪    币: 27
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
寂寞寒烟 活跃值 2014-11-16 07:32
8
0
我上面发的代码始终打印 dr6 为0
雪    币: 7
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
xiaoming 活跃值 2014-12-4 21:44
9
0
从你的代码,我可以看出你对OD插件的了解程度要远胜于我,我想了一下,感觉这如果不是数据对齐方面出了问题,那就是tcc的BUG了。

抱歉。对于tcc我个人了解也不是太多。
雪    币: 27
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
寂寞寒烟 活跃值 2014-12-5 08:39
10
0
哦楼主谦虚了,我用那个GetThreacContext代替了,是可以实现硬件条件断点的,但是你这个插件里面自带的函数
void tsa_print(int i_color,char *fmt,...);//在TS输出窗口显示信息
也许还有其他函数
插件提示找不到符号,我觉得你是不是把版本放错了啊
游客
登录 | 注册 方可回帖
返回