第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

时间:2022-12-28 20:22:36

OllyDbg 操作菜单栏、工具栏、快捷键

C++调用加强

目录

OllyDbg 操作菜单栏、工具栏、快捷键    1

一、    载入观察    1

1、静态载入观察:    1

2、OD动态观察    1

二、    初步尝试下断查找目标    1

1、如何下断    1

2、接下来有两个选择:    1

2.1手动F9运行目标    1

2.2设条件断点    1

2.3 CALL调用时堆栈小解    1

3、初步断点目标 (条件触发情况)    1

三、调用栈回溯    1

1、回溯到无关子过程跳过    1

1.1 CALL地址定位小解    1

2、用户领空小心回溯    1

四、悬疑目标前下断    1

五、另一个查找怀疑目标的方法    1

六、牛逼的IDA加载分析    1

七、其他    1

1、入口OEP特征    1

2、好文章    1

2.1、ESP定律背后的原理之一:0x12FFC4,为什么是这个数    1

2.2、回复里链接文章    1

一般第一次总是比较傻的,但是我们在了解好逆向需要具备哪些(指令懂,君子善假于物也,这句话我经常用哈,当时写作文和说话中),就比较有想法思路了,凡是要有准备嘛。

就好比打游戏,自己操作好,打的才得心应手,打的妙。一般把第一次叫做试探。如第一次打某个BOSS,一般不看攻略或官方介绍,你总要多次尝试,(如果性子不好,急了可以放手下次从开头继续打)。这样熟悉了之后,就容易了。还有更感兴趣,可以多次刷,并掌握技巧,打的BOSS无法还手,一直悬空打那个爽啊。一个币打通游戏机社拳皇,久了被发现结果老板调了难度。

一般东西都是人做的,使用火影里鼬的话,没有不破的。凡是怕——多次试探而熟生巧。

所以第一次记录一下,主要是怎么在OllyDbg用知识,当时玩得不是很好,欢迎拍砖指导。

  1. 载入观察

1、静态载入观察:

PEiD未发现什么,一般编译后都会显示什么的吧。入口地址=入口点+映像基址=0024D86F+00400000=0064D86F。

可见各个模块很清晰,不像经过加工的样子。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

看资源,资源可见,很好啊,初始是注册的。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

2、OD动态观察

OllyDbg载入后第一条语句是0064D86F > $ E8 72DD0000 call 0065B5E6,见入口OEP特征

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

F9运行,可以看到句柄等动态分配的,看到小对话框,是未注册信息,回到OD主界面,按[Alt+M],可以查看窗口信息,如图下2图。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

其实资源来自:

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

  1. 初步尝试下断查找目标

逆向查找目标有时是很辛苦的,有时并不是说失败成功的弹窗前一句就是关键。所以要善假于物,利用各种有利工具及其功能,之后多次熟生巧。

个人觉得逆向之破,核心就是耐心地搜索和断点来捡关键的分析。

1、如何下断

下什么断,这里就是下简单的断,其他暂时用不到啊。

对话框一个Static控件有Unrigistered字样,肯定会调用某API的如SetWindowText(SetDlgItemText也会调它,见下图)。在这个API下断,运行,第一次断下看到如下图,并且是UNICODE版的SetWindowTextW。

说明:断点都是打在USER32模块,是因为API SetWindowTextA/W就是这个dll导出的。而这个是系统的,最安全,不管怎么调用这个函数(如导入表没SetWindowTextA/W可能是用了LoadLibary和GetProcAddress,或者自己实现的类似的功能;类似于加壳过的,就要看最后附加的文章去脱壳,然后再从这里继续;即数学方法之一——化归,不管奥数奥物理或者难题简单题都会有这类问题归一)总规会走这条路的。

可以通过下面步骤找到下断位置,查找模块中的名字(在程序领空找也行,因为前面我们看到模块导入了或者选择已加载模块USER32找)->直接打字搜索SetWindowText开头的名字->双击进入反汇编界面,设置断点。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

2、接下来有两个选择:

2.1手动F9运行目标

直到看到右下角堆栈窗口显示的第二个参数Text直接为This is unregistered…,(不是This is a registered copy…难道初始加载资源设置上面那个注册的不是SetWindowTextW搞的吗)。

2.2设条件断点

BOOL WINAPI SetWindowText(

_In_ HWND hWnd,

_In_opt_ LPCTSTR lpString

);

User32.dll里的。

还有就是在这个断点(光标要在这行)按[Shift+F2]设置条件断点(只有满足条件才断点)。下个条件断点表达式(如上图):

UNICODE [[ESP+8]] == "Th"

或者有这个cmdBar插件,一开始就在这里下条件断点,[Alt+B]断点视窗就多了一个断点,若存在而Disable就启用。

(格式:bp address, string)

bp SetWindowTextW, UNICODE [[ESP+8]] == "Th"

2.3 CALL调用时堆栈小解

举例:BOOL WINAPI SetWindowText(_In_ HWND hWnd, _In_opt_ LPCTSTR lpString);

所以调用SetWindowTextW会把两个参数从右向左(WINAPI的调用约定,其实就是stdcall,是因为#define WINAPI __stdcall。其他调用还有__cdecl,__fastcall,__thiscall等,详细请网络搜索)压栈push,ESP减4。

断到此过程前开头,ESP上存放的是返回后的下一条语句地址004C3B8C。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

下面截图感受下,调用时相对ESP地址上的值情况:

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

3、初步断点目标 (条件触发情况)

直到出现或一步断下后,[Alt+K]查看堆栈或者右下角堆栈窗口。在保护模式下,栈顶是这个子过程的下一个地址。右键可以选择回去。我们可以看到如下:

条件断点触发了,这里我把有用信息框出来了,比照一下。

【解释】ESP+8的值是0012E1F0,其实也是一个地址;

这个地址所指向的内存,存放的内容是00E2F8D0,其实也是一个地址;

在堆栈窗口-右键黄色那行选择数据窗口中跟随,就可在左边那个窗口看到这个地址开始内存里的值了,由于是UNICODE字符串,所以要选好显示方式,不然OllyDbg可能想显示乱码。

注注】此比较是把这个字符串转为ASCII,再和你给的"Th"常量字符串比较的,不匹配长度,类似正则表达式^xxx.*这里xxx就是你的菜。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

从图上, USER32 里的 SetWindowTextW映射到本程序的进程地址空间后的样子(地址比较大吧)。我们需要回到程序领空(地址小,就是win32应用映射后的text),执行到用户代码[Alt+F9]。

三、

调用栈回溯

主要查找可疑代码,如判断跳转(JZ、JMP等,一般前面有比较指令等会改变标志位)等。

改变跳转条件

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

如何回溯,从编程人员角度想想可能的调用栈举例情况:

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

首先是回溯到用户程序领空,因为前一个断点都是打在系统领空的。

再就是找调用前有跳过断点call(子call,子子call,…)的判断跳转。

1、回溯到无关子过程跳过

直接看出无关的子调用过程直接跳过,执行到返回并步过,到上级过程,再查看是否相关(系统API或封装的一般是直接跳过的子过程)。

回到进入子过程的下一个位置,就是前一步右下角堆栈的地址。这里好多API放一起可能是被封起来用的,这是一个子过程,往上看到入口地址004C3B4A就是SetDlgItemText(int cotrolId, TCHAR *pszText)这样。这里需要再往上一级调用跑。只有几步就回去了,直接步过回去,就可以。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

1.1 CALL地址定位小解

或者[Alt+K]打开调用堆栈,记录了简单调用过程,???是未知,可能是动态调用,还没确认,如call eax等。

解释:正常用高级语言写的程序,函数在运行时都有固定位置,反汇编后就是call xxxxxxxx,静态的。但是凡是总有例外,如果程序员使用了内嵌asm、函数指针等,或者对象中的函数,即虚函数(编译时不能确定只能动态获取)。

#include <stdio.h>
class A
{
public:
    void function(){printf("Hello World");}

};

class B
{
public:
    virtual void function(){printf("Hello World");}//虚函数C++多态
};

int _tmain(int argc, _TCHAR* argv[])
{
    A* p1 = NULL;
    p1->function();  // ok. print "Hello World".

    B* p2 = NULL;
    p2->function();  // crash.
};
;vs2013 debug on windows8-x64

00BA5B80  push        ebp
00BA5B81  mov         ebp,esp
00BA5B83  sub         esp,0D8h
00BA5B89  push        ebx
00BA5B8A  push        esi
00BA5B8B  push        edi
00BA5B8C  lea         edi,[ebp-0D8h]
00BA5B92  mov         ecx,36h
00BA5B97  mov         eax,0CCCCCCCCh
00BA5B9C  rep stos    dword ptr es:[edi]  ;重复执行stos指令(将eax中的值拷贝到ES:EDI指向的地址)直到ecx=0
    A* p1 = NULL;

    p1->function();  // ok. print "Hello World".
00BA5BA5  mov         ecx,dword ptr [p1]
00BA5BA8  call        A::function (0BA169Ah)  ;

    B* p2 = NULL;

    p2->function();  // crash.
00BA5BB4  mov         eax,dword ptr [p2]
00BA5BB7  mov         edx,dword ptr [eax]
00BA5BB9  mov         esi,esp               ;Debug模式下添加的东西,用于栈平衡检查,保存栈指针。
00BA5BBB  mov         ecx,dword ptr [p2]
00BA5BBE  mov         eax,dword ptr [edx]
00BA5BC0  call        eax
00BA5BC2  cmp         esi,esp   ;Debug模式下添加的东西,用于栈平衡检查,期待esp等于保存在esi里的值。
00BA5BC4  call        __RTC_CheckEsp (0BA14A1h) ;Debug模式下添加的东西,用于栈平衡检查。 

0044760F |. E8 1EC30700 call 004C3932 ; call跳转地址(过程开始地址) = call起始位置+ call后面的操作数+5(指令字节长度)= call结束位置(下一条语句起始位置)+call后面的操作数。

00447614 |. 8BC8 mov ecx, eax ; 004C3932 = 0044760F + 0007C31E + 5 = 00447614 + 0007C31E,注意:机器码E8后面所跟的32位数是little-endian格式(x86是小尾模式)的,低位在前,高位在后。

跳转主要就是改变EIP指令寄存器,可以动态跟踪一下:call执行前和步入后,查看寄存器窗口里EIP的值改变情况。由于EIP不能直接改变,所以可以借助无条件跳转JMP来跳到任意位置,以此间接改变EIP。

Opcode CALL

CPU: 8086+

Type of Instruction: User

Instruction: CALL procadr

Physical form:

| Near call - withing the same segment 段内调用

| Far call - call to another segment 段间调用

E8 cw CALL rel16 ; Near call, operand specifies relative displacement to next instruction 操作数指定了下一条指令的相对位移

E8 cd CALL rel32 ; Near call, operand specifies relative displacement to next instruction

FF /2 CALL r/m16 ; Near call, absolute address

FF /2 CALL r/m32 ; Near call, absolute address

9A cd CALL ptr16:16 ; Far call, absolute addres

9A cp CALL ptr16:32 ; Far call, absolute address

FF /3 CALL m16:16 ; Far call, absolute address

FF /3 CALL m16:32 ; Far call, absolute address

[Alt+K] 调用堆栈界面

    双击【过程(Procedure/arguments)】栏的项目或某行右键菜单选择【跟随过程(follow) /(show procedure)】,则会进入CPU界面定位于反汇编窗口内的对应的方法开头;

    双击【调用从(Called from)】栏的项目或某行右键菜单选择【跟随Caller(follow) / (show call)】,则会进入CPU界面定位于反汇编窗口内的相应的call语句地址。

    第一行【Stack】列式当前断点ESP值,指向的内容是过程USER32.SetWindowTextW返回后的地址,即call语句的下一句地址,显示在【数据】一列。

    其他行是上一级call历史记录,再上一级的call,可以看出从入口第一个ESP(一般为0x12FFC4,详见入口ESP)到当前断点的所有过程都记录下来了。

    这里是无法记录每级别同等层次的其他call过程,即曾调用过的所有非直系的call,因为已经出栈了,但是可以使用跟踪来记录所有。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

2、用户领空小心回溯

回去后看到,文本已经变成未注册的了,前面有好多判断跳转,貌似都不是好跳转。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

四、悬疑目标前下断

在前一个调用004C3B4A设置断点,其他的删除,先设距离大点,或者也可再设置一个,这句(Local.22是本地变量,OD命名见下图-栈图,即EBP - 22. * 4 = EBP - 88. = EBP - 58):

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

CPU Disasm

地址 十六进制数据 指令 注释

004475FC |. 8D4D A8 LEA ECX,[LOCAL.22]

重新运行[Ctrl+F2]。再按[F9]到断点处,鼠标点击工具栏的W图标按钮(Alt+W)打开窗口视图,如下图:

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

如果继续运行就变成未注册。

我们会发现这个过程,其实只是操作界面的过程。

其实,通过点击前面各个跳转指令看跳转位置,发现没有跳过加载资源839的那块语句和SetWindowTextW的。

我们猜测注册后打开时弹窗不该出现,但是,主界面Help->About菜单或工具栏?按钮也会弹出此窗口,且是同一段代码,可以通过断点或者MFC编程规则查找OnCommand的处理。所以还是某处判断并调用此段代码。还有一点,前面推测C++封装代码,还有OD自助推测CDialog可推知是MFC写的,其他详细见符号分析

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

双击USER32.CreateDialogIndirectParamW调用来自进入call位置,在上面跟随标签。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

这个窗口制造返回前会调用,参数DialogFunc,如下图

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

前一个断下后在sr32.AfxDlgProc(HWND__ *,uint,uint,long)(推测 hWnd,Msg,wParam,lParam)或者关心的跳转CALL DWORD PTR DS:[EDX+174]下断,可以看到对参数2进行了特别处理,意思是消息为WM_INITDIALOG= $0110;时不跳转而调用对象方法。

观察右下角堆栈窗口的第二个参数,第一个消息是 WM_SETFONT= $0030;之后就是WM_INITDIALOG= $0110;了。此时CALL DWORD PTR DS:[EDX+174]是对象方法的调用,会进入我们前面调用SetWindowtextW的方法里。

以上,通过IDA可以方便查看WM_INITDIALOG的消息处理,没有能跳过的跳转,故这个调用舍去,继续分析上一级调用:

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

一以下是调用栈,{}块是同级调用栈

.    call    sub_4015FA ;this->sub_401FA(int, HWND, HINSTANCE)调用以下过程:

.text:00465E90    int __thiscall sub_465E90(struct CWnd *, int, HWND hWndParent, HINSTANCE hInstance); 

{
.text:004664F9    LoadResourse(IDC_ABOUTDLG_102, );
.text:00465E90    int __thiscall sub_465E90(struct CWnd *, int, HWND hWndParent, HINSTANCE hInstance);
}
.    CreateDialogIndirectParamW(hInst, NULL, MAINDLG_Template, AfxDlgProc, );
.text:004B8C5F    BOOL __stdcall AfxDlgProc(HWND, UINT, WPARAM, LPARAM);?AfxDlgProc@@YGHPAUHWND__@@IIJ@Z proc near
.text:0043B980    int __thiscall sub_43B980(CWnd *this);

{
.text:004664F9    LoadResourse(IDC_MAINDLG_100, );
.text:00465E90    int __thiscall sub_465E90(struct CWnd *, int, HWND hWndParent, HINSTANCE hInstance);
}
.    CreateDialogIndirectParamW(hInst, NULL, MAINDLG_Template, AfxDlgProc, );
.text:004B8C5F    BOOL __stdcall AfxDlgProc(HWND, UINT, WPARAM, LPARAM);?AfxDlgProc@@YGHPAUHWND__@@IIJ@Z proc near
.    int __thiscall sub_447210(CWnd *this);

另外说下标记处调用,调用跳转

.text:004B8C5F
.text:004B8C5F ; =============== S U B R O U T I N E =======================================
.text:004B8C5F
.text:004B8C5F ; Attributes: library function bp-based frame
.text:004B8C5F
.text:004B8C5F ; BOOL __stdcall AfxDlgProc(HWND, UINT, WPARAM, LPARAM)
.text:004B8C5F ?AfxDlgProc@@YGHPAUHWND__@@IIJ@Z proc near
.text:004B8C5F                                         ; CODE XREF: _AfxCommDlgProc(HWND__ *,uint,uint,long)+B3p
.text:004B8C5F                                         ; AfxOleHookProc(HWND__ *,uint,uint,long)+19p
.text:004B8C5F                                         ; DATA XREF: ...
.text:004B8C5F
.
.text:004B8C5F arg_4           = dword ptr  0Ch
.text:004B8C5F
.text:004B8C5F                 mov     edi, edi
.text:004B8C61                 push    ebp
.text:004B8C62                 mov     ebp, esp
.text:004B8C64                 cmp     [ebp+arg_4], 110h
.text:004B8C6B                 jnz     short loc_4B8C97
.text:004B8C6D                 push    [ebp+arg_0]     ; HWND
.text:004B8C70                 call    ?FromHandlePermanent@CWnd@@SGPAV1@PAUHWND__@@@Z ; CWnd::FromHandlePermanent(HWND__ *)
.text:004B8C75                 push    eax             ; struct CObject *
.text:004B8C76                 push    offset off_73E9BC ; struct CRuntimeClass *
.text:004B8C7B                 call    ?AfxDynamicDownCast@@YAPAVCObject@@PAUCRuntimeClass@@PAV1@@Z ; AfxDynamicDownCast(CRuntimeClass *,CObject *)
.text:004B8C80                 pop     ecx
.text:004B8C81                 pop     ecx
.text:004B8C82                 test    eax, eax
.text:004B8C84                 jz      short loc_4B8C92
.text:004B8C86                 mov     edx, [eax]
.text:004B8C88                 mov     ecx, eax
.text:004B8C8A                 call    dword ptr [edx+174h]
.text:004B8C90                 jmp     short loc_4B8C99
.text:004B8C92 ; ---------------------------------------------------------------------------
.text:004B8C92
.text:004B8C92 loc_4B8C92:                             ; CODE XREF: AfxDlgProc(HWND__ *,uint,uint,long)+25j
.text:004B8C92                 xor     eax, eax
.text:004B8C94                 inc     eax
.text:004B8C95                 jmp     short loc_4B8C99
.text:004B8C97 ; ---------------------------------------------------------------------------
.text:004B8C97
.text:004B8C97 loc_4B8C97:                             ; CODE XREF: AfxDlgProc(HWND__ *,uint,uint,long)+Cj
.text:004B8C97                 xor     eax, eax
.text:004B8C99
.text:004B8C99 loc_4B8C99:                             ; CODE XREF: AfxDlgProc(HWND__ *,uint,uint,long)+31j
.text:004B8C99                                         ; AfxDlgProc(HWND__ *,uint,uint,long)+36j
.text:004B8C99                 pop     ebp
.text:004B8C9A                 retn    10h
.text:004B8C9A ?AfxDlgProc@@YGHPAUHWND__@@IIJ@Z endp
.text:004B8C9A

在这里寄存器,然后跳到

CPU窗口 - 主线程, 模块 sr32

EAX 0012F1D4 UNICODE "鬪s"
ECX 0012F1D4 UNICODE "鬪s"
EDX 00735EF4 sr32.off_735EF4
EBX 001B023A
ESP 0012EB7C UNICODE "悓K"
EBP 0012EB80
ESI 004B8C5F sr32.?AfxDlgProc@@YGHPAUHWND__@@IIJ@Z
EDI
EIP 004020DB sr32.sub_4020DB

C   ES  32Bit (FFFFFFFF)
P   CS (FFFFFFFF)
A   SS  32Bit (FFFFFFFF)
Z   DS  32Bit (FFFFFFFF)
S   FS 003B 32Bit 7FFDF000(FFF)
T   GS  NULL
D
O   LastErr  ERROR_SUCCESS
EFL  (NO,NB,NE,A,NS,PE,GE,G)

跳转表,被交叉引用在偏移量.rdata里,这里直接到跳转地址。。。

.text:004020D1
.text:004020D1 ; =============== S U B R O U T I N E =======================================
.text:004020D1
.text:004020D1 ; Attributes: thunk
.text:004020D1
.text:004020D1 sub_4020D1      proc near               ; CODE XREF: sub_40BF60+45p
.text:004020D1                                         ; sub_40BF60+5Cp ...
.text:004020D1                 jmp     sub_40BE40
.text:004020D1 sub_4020D1      endp
.text:004020D1
.text:004020D6 ; ---------------------------------------------------------------------------
.text:004020D6                 jmp     loc_447E80
.text:004020DB
.text:004020DB ; =============== S U B R O U T I N E =======================================
.text:004020DB
.text:004020DB ; Attributes: thunk
.text:004020DB
.text:004020DB sub_4020DB      proc near               ; DATA XREF: .rdata:00736068o
.text:004020DB                 jmp     sub_43B980
.text:004020DB sub_4020DB      endp
.text:004020DB
.text:004020E0
.text:004020E0 ; =============== S U B R O U T I N E =======================================
.text:004020E0
.text:004020E0 ; Attributes: thunk
.text:004020E0
.text:004020E0 sub_4020E0      proc near               ; DATA XREF: .rdata:0073BEE4o
.text:004020E0                 jmp     sub_479920
.text:004020E0 sub_4020E0      endp
.text:004020E0
.text:004020E5
.text:004020E5 ; =============== S U B R O U T I N E =======================================
.text:004020E5
.text:004020E5 ; Attributes: thunk
.text:004020E5
.text:004020E5 sub_4020E5      proc near               ; DATA XREF: .rdata:00734E44o
.text:004020E5                 jmp     sub_429800
.text:004020E5 sub_4020E5      endp
.text:004020E5

过程为??,调用来自位置。。。。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

五、另一个查找怀疑目标的方法

以另外一个地方,显示受限功能弹窗的为例。

85E=2142. Only up to 5 files can be replaced this session in the Unregistered Version.$0ADo you want to see the Ordering Information?

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

回到OllyDbg按下[F12]或工具栏的暂停按钮,状态栏最右边就会出现暂停字样。

再用[Alt+K]打开前面提到的调用堆栈,因为显示的比CPU界面(主界面)右下角堆栈窗口(不反对放大,然后往下回溯调用)简单,容易看。没有符号详细见符号分析。工具利用起来事半功倍。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

点击sr32.AfxMessageBox(uint,uint,uint)回到哪里调用它的。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

前面跳转就是控制显示弹窗,在这下断,重新测试替换功能,手动设置标志位寄存器的Z标识或者直接改为无条件跳转JMP。

猜想结果:如果8个文件有未成功,需要查看弹窗判断和替换的循环操作是否各有判断。

即可能类似这样:

void DoReplace()

{

BOOL bUnregistered = CheckUnregistered();

If(bUnregistered)

{

UnregisteredUserReplaceHandler(BOOL bFirstReplace, BOOL bShowBackupTip){

If(count > 5)

{

ShowLimitedTip(){

sr32.AfxMessageBox(uint,uint,uint);

};

}

};

If(count > 5)

{

count = 5;

}

}

}

发现没有弹窗但是还只是替换了5个。查找和5比较或间接比较的地方。

个人觉得经验就是:把别人的"写"成自己的(积累的快),自己的再不断探探究究(看自己实践)。

六、牛逼的IDA加载分析

OllyDbg可以通过一定办法加载IDA的map文件,导入符号。

如下图,OllyDbg一加载的场景截图

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

当用IDA打开后,会在后台不断解析符号。

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)

[Shift+S]保存,类似于VM虚拟机保存快照功能,下次好快速进入。

七、其他

1、入口OEP特征

网络上有人的总结:

Microsoft Visual C++ 6.0

00496EB8 >/$ 55 PUSH EBP ; (初始 cpu 选择)

00496EB9 |. 8BEC MOV EBP,ESP

00496EBB |. 6A FF PUSH -1

00496EBD |. 68 40375600 PUSH Screensh.00563740

00496EC2 |. 68 8CC74900 PUSH Screensh.0049C78C ; SE 处理程序安装

00496EC7 |. 64:A1 0000000>MOV EAX,DWORD PTR FS:[0]

00496ECD |. 50 PUSH EAX

00496ECE |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP

00496ED5 |. 83EC 58 SUB ESP,58

Microsoft Visual Basic 5.0 / 6.0

00401166 - FF25 6C104000 JMP DWORD PTR DS:[<&MSVBVM60.#100>] ; MSVBVM60.ThunRTMain

0040116C > 68 147C4000 PUSH PACKME.00407C14

00401171 E8 F0FFFFFF CALL <JMP.&MSVBVM60.#100>

00401176 0000 ADD BYTE PTR DS:[EAX],AL

00401178 0000 ADD BYTE PTR DS:[EAX],AL

0040117A 0000 ADD BYTE PTR DS:[EAX],AL

0040117C 3000 XOR BYTE PTR DS:[EAX],AL

或省略第一行的JMP

00401FBC > 68 D0D44000 push dumped_.0040D4D0

00401FC1 E8 EEFFFFFF call <jmp.&msvbvm60.ThunRTMain>

00401FC6 0000 add byte ptr ds:[eax],al

00401FC8 0000 add byte ptr ds:[eax],al

00401FCA 0000 add byte ptr ds:[eax],al

00401FCC 3000 xor byte ptr ds:[eax],al

00401FCE 0000 add byte ptr ds:[eax],al

BC++

0040163C > $ /EB 10 JMP SHORT BCLOCK.0040164E

0040163E |66 DB 66 ; CHAR 'f'

0040163F |62 DB 62 ; CHAR 'b'

00401640 |3A DB 3A ; CHAR ':'

00401641 |43 DB 43 ; CHAR 'C'

00401642 |2B DB 2B ; CHAR '+'

00401643 |2B DB 2B ; CHAR '+'

00401644 |48 DB 48 ; CHAR 'H'

00401645 |4F DB 4F ; CHAR 'O'

00401646 |4F DB 4F ; CHAR 'O'

00401647 |4B DB 4B ; CHAR 'K'

00401648 |90 NOP

00401649 |E9 DB E9

0040164A . |98E04E00 DD OFFSET BCLOCK.___CPPdebugHook

0040164E > \A1 8BE04E00 MOV EAX,DWORD PTR DS:[4EE08B]

00401653 . C1E0 02 SHL EAX,2

00401656 . A3 8FE04E00 MOV DWORD PTR DS:[4EE08F],EAX

0040165B . 52 PUSH EDX

0040165C . 6A 00 PUSH 0 ; /pModule = NULL

0040165E . E8 DFBC0E00 CALL <JMP.&KERNEL32.GetModuleHandleA> ; \GetModuleHandleA

00401663 . 8BD0 MOV EDX,EAX

Borland Delphi 6.0 - 7.0

00509CB0 > $ 55 PUSH EBP

00509CB1 . 8BEC MOV EBP,ESP

00509CB3 . 83C4 EC ADD ESP,-14

00509CB6 . 53 PUSH EBX

00509CB7 . 56 PUSH ESI

00509CB8 . 57 PUSH EDI

00509CB9 . 33C0 XOR EAX,EAX

00509CBB . 8945 EC MOV DWORD PTR SS:[EBP-14],EAX

00509CBE . B8 20975000 MOV EAX,unpack.00509720

00509CC3 . E8 84CCEFFF CALL unpack.0040694C

易语言入口

00401000 > E8 06000000 call dump_.0040100B

00401005 50 push eax

00401006 E8 BB010000 call <jmp.&KERNEL32.ExitProcess>

0040100B 55 push ebp

0040100C 8BEC mov ebp,esp

0040100E 81C4 F0FEFFFF add esp,-110

00401014 E9 83000000 jmp dump_.0040109C

00401019 6B72 6E 6C imul esi,dword ptr ds:[edx+6E],6C

0040101D 6E outs dx,byte ptr es:[edi]

也可能是这样的入口

Microsoft Visual C++ 6.0 [Overlay] E语言

00403831 >/$ 55 PUSH EBP

00403832 |. 8BEC MOV EBP,ESP

00403834 |. 6A FF PUSH -1

00403836 |. 68 F0624000 PUSH Nisy521.004062F0

0040383B |. 68 A44C4000 PUSH Nisy521.00404CA4 ; SE 处理程序安装

00403840 |. 64:A1 0000000>MOV EAX,DWORD PTR FS:[0]

00403846 |. 50 PUSH EAX

00403847 |. 64:8925 00000>MOV DWORD PTR FS:[0],ESP

MASM32 / TASM32入口

00401258 >/$ 6A 00 push 0 ; /pModule = NULL

0040125A |. E8 47000000 call <jmp.&kernel32.GetModuleHandleA> ; \GetModuleHandleA

0040125F |. A3 00304000 mov dword ptr ds:[403000],eax

00401264 |. 6A 00 push 0 ; /lParam = NULL

00401266 |. 68 DF104000 push dump.004010DF ; |DlgProc = dump.004010DF

0040126B |. 6A 00 push 0 ; |hOwner = NULL

0040126D |. 6A 65 push 65 ; |pTemplate = 65

0040126F |. FF35 00304000 push dword ptr ds:[403000] ; |hInst = NULL

00401275 |. E8 56000000 call <jmp.&user32.DialogBoxParamA> ; \DialogBoxParamA

004A2ADC > $ E8 B6A40000 call 记事本.004ACF97

004A2AE1 .^ E9 16FEFFFF jmp 记事本.004A28FC

004A2AE6 CC int3

004A2AE7 CC int3

004A2AE8 CC int3

004A2AE9 CC int3

004A2AEA CC int3

004A2AEB CC int3

004A2AEC CC int3

004A2AED CC int3

004A2AEE CC int3

004A2AEF CC int3

004A2AF0 /$ 8B4C24 04 mov ecx,dword ptr ss:[esp+4]

004A2AF4 |. F7C1 03000000 test ecx,3

004A2AFA |. 74 24 je short 记事本.004A2B20

004A2AFC |> 8A01 /mov al,byte ptr ds:[ecx]

004A2AFE |. 83C1 01 |add ecx,1

2、好文章

2.1、ESP定律背后的原理之一:0x12FFC4,为什么是这个数

标 题: 【原创】ESP定律背后的原理之一:0x12FFC4,为什么是这个数

作 者: tnttools

时 间: 2008-02-05,16:13:41

链 接: http://bbs.pediy.com/showthread.php?t=59352

ESP定律背后的原理之一:0x12FFC4

ESP定律:如果压缩壳执行前后的堆栈会维持平衡,在12FFC0上下读写断点,会中断在OEP的第一条指令push ebp上。那么各位有没有探究过ESP的尾数值为什么不是0xFFFC,而是0x0FFC4?这是由windows源代码的实现所确定的。

Windows创建进程的函数链为kernel32.dll!_CreateProcessInternalW -> … -> kernel32.dll!_BaseProcessStartThunk() -> kernel32.dll!_BaseProcessStart() -> EP

在进入_BaseProcessStartThunk()时,堆栈的状态确实为

+ 0012FFFC 00000000 <- ESP

---------------------------------------------------------<code>

_BaseProcessStartThunk@8 proc near

xor ebp, ebp

push eax

push 0

jmp _BaseProcessStart@4 ; BaseProcessStart(x)

_BaseProcessStartThunk@8 endp

----------------------------------------------------------</code>

在执行完_BaseProcessStartThunk时,堆栈的状态为

+ 0012FFFC 00000000

+ 0012FFF8 EAX

+ 0012FFF4 0x00000000 <- ESP

---------------------------------------------------------<code>

_BaseProcessStart proc

push 0Ch

push offset dword_7C816FE0

call __SEH_prolog

and [ebp+ms_exc.disabled], 0

push 4

lea eax, [ebp+8]

push eax

push 9

push 0FFFFFFFEh

call ds:__imp__NtSetInformationThread@16 ; NtSetInformationThread(x,x,x,x)

call dword ptr [ebp+8]

push eax ; dwExitCode

call _ExitThread@4

nop

nop

nop

---------------------------------------------------------</code>

在执行完BaseProcessStart()后,堆栈的状态为

+ 0012FFFC 0x00000000

+ 0012FFF8 OldEAX -2-> EntryPoint By NtSetInformationThread()

+ 0012FFF4 reserved, inited to 0x00000000

+ 0012FFF0 OldEBP(0x00000000) <-p- NowEBP

+ 0012FFEC TryLevel, inited to 0xFFFFFFFF

+ 0012FFE8 ScopeTable

+ 0012FFE4 __except_handler3 in kernel32.dll

+ 0012FFE0 0xFFFFFFFF <-p- fs:00h

+ 0012FFDC ExceptionInfo, Parameter of UnhandledExceptionFilter()

+ 0012FFD8 OldESP(0x0012FFC8)

+ 0012FFD4 ExceptionCode, Parameter of kernel32.dll!ExitProcess

+ 0012FFD0 EBX(pPEB)

+ 0012FFCC ESI

+ 0012FFC8 EDI <-p- OldESP

+ 0012FFC4 retaddr in kernel32.dll!_BaseProcessStartThunk

<-p- NowESP

附:

DWORD SizeOfStackReserve; // 0x48-4b

DWORD SizeOfStackCommit; // 0x4c-4f

DWORD SizeOfHeapReserve; // 0x50-53

DWORD SizeOfHeapCommit; // 0x54-57

这是IOH中的四个域。

Reserved保留的, Committed提交的是两种类型的虚拟内存。

Reserved指这段内存已有用途,不能再被分配;Committed提交的内存指的是已经与物理内存有映射的虚拟内存段(当然也可以被移到硬盘上的缓存文件pagefile.sys中)。因为Stack, Heap这两种类型的内存段都有随着程序的运行尺寸不断增大的特性,所以一开始不必占用太多宝贵的物理内存,当它们用完了,会引发内存异常,windows内存管理器就又为程序分配一部分。

SizeOfStackReserve 程序开始时保留用作堆栈空间的内存段的大小

SizeOfStackCommit 程序开始时在保留的堆栈内存段中与物理内存映射的提交的内存段的大小

SizeOfHeapReserve 程序开始时保留用作堆空间的内存段的大小

SizeOfHeapCommit 程序开始时在保留的堆内存段中与物理内存映射的提交的内存段的大小

2.2、回复里链接文章

那么各位有没有想过为什么在进入任何一个程序时,ESP的值都是0x12FFC4。

脱壳入门初级教学http://bbs.pediy.com/showthread.php?t=20366

注意:并不是所有程序加载时,ESP的值是0012FFC4,这个值是什么由操作系统决定,将SizeOfStackCOmmit改大ESP就会变,这是因为操作系统从这个页向上找一个足够大地方当作stack了(感谢forgot解释)。

标 题: 脱壳基础知识入门及FAQ

作 者: kanxue

时 间: 2006-01-14 17:20

链 接: http://bbs.pediy.com/showthread.php?t=20366

附《劝学》

非课文,摘自网络。

君子曰:学不可以已。

  青,取之于蓝而青于蓝;冰,水为之而寒于水。木直中绳,輮(左应为"车",原字已废除)以为轮,其曲中规。虽有槁暴,不复挺者,輮使之然也。故木受绳则直,金就砺则利,君子博学而日参省乎己,则知明而行无过矣。

  故不登高山,不知天之高也;不临深溪,不知地之厚也;不闻先王之遗言,不知学问之大也。干、越、夷、貉之子,生而同声,长而异俗,教使之然也。诗曰:"嗟尔君子,无恒安息。靖共尔位,好是正直。神之听之,介尔景福。"神莫大于化道,福莫长于无祸。

  吾尝终日而思矣,不如须臾之所学也;吾尝跂而望矣,不如登高之博见也。登高而招,臂非加长也,而见者远;顺风而呼,声非加疾也,而闻者彰。假舆马者,非利足也,而致千里;假舟楫者,非能水也,而绝江河。君子生非异也,善假于物也。

  南方有鸟焉,名曰蒙鸠,以羽为巢,而编之以发,系之苇苕,风至苕折,卵破子死。巢非不完也,所系者然也。西方有木焉,名曰射干,茎长四寸,生于高山之上,而临百仞之渊,木茎非能长也,所立者然也。蓬生麻中,不扶而直;白沙在涅,与之俱黑。兰槐之根是为芷,其渐之滫,君子不近,庶人不服。其质非不美也,所渐者然也。故君子居必择乡,游必就士,所以防邪辟而近中正也。

  物类之起,必有所始。荣辱之来,必象其德。肉腐出虫,鱼枯生蠹。怠慢忘身,祸灾乃作。强自取柱,柔自取束。邪秽在身,怨之所构。施薪若一,火就燥也,平地若一,水就湿也。草木畴生,禽兽群焉,物各从其类也。是故质的张,而弓矢至焉;林木茂,而斧斤至焉;树成荫,而众鸟息焉。醯酸,而蚋聚焉。故言有招祸也,行有招辱也,君子慎其所立乎!

  积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里;不积小流,无以成江海。骐骥一跃,不能十步;驽马十驾,功在不舍。锲而舍之,朽木不折;锲而不舍,金石可镂。蚓无爪牙之利,筋骨之强,上食埃土,下饮黄泉,用心一也。蟹六跪而二螯,非蛇鳝之穴无可寄托者,用心躁也。

  是故无冥冥之志者,无昭昭之明;无惛惛之事者,无赫赫之功。行衢道者不至,事两君者不容。目不能两视而明,耳不能两听而聪。螣蛇无足而飞,鼫鼠五技而穷。《诗》曰:"尸鸠在桑,其子七兮。淑人君子,其仪一兮。其仪一兮,心如结兮!"故君子结于一也。

  昔者瓠巴鼓瑟,而流鱼出听;伯牙鼓琴,而六马仰秣。故声无小而不闻,行无隐而不形 。玉在山而草润,渊生珠而崖不枯。为善不积邪?安有不闻者乎?

  学恶乎始?恶乎终?曰:其数则始乎诵经,终乎读礼;其义则始乎为士,终乎为圣人, 真积力久则入,学至乎没而后止也。故学数有终,若其义则不可须臾舍也。为之,人也;舍 之,禽兽也。故书者,政事之纪也;诗者,中声之所止也;礼者,法之大分,类之纲纪也。 故学至乎礼而止矣。夫是之谓道德之极。礼之敬文也,乐之中和也,诗书之博也,春秋之微 也,在天地之间者毕矣。 君子之学也,入乎耳,着乎心,布乎四体,形乎动静。端而言,蝡而动,一可以为法则。小人之学也,入乎耳,出乎口;口耳之间,则四寸耳,曷足以美七尺之躯哉!古之学者为己,今之学者为人。君子之学也,以美其身;小人之学也,以为禽犊。故不问而告谓之傲,问一而告二谓之囋。傲、非也,囋、非也;君子如向矣。

  学莫便乎近其人。礼乐法而不说,诗书故而不切,春秋约而不速。方其人之习君子之说,则尊以遍矣,周于世矣。故曰:学莫便乎近其人。

  学之经莫速乎好其人,隆礼次之。上不能好其人,下不能隆礼,安特将学杂识志,顺诗书而已耳。则末世穷年,不免为陋儒而已。将原先王,本仁义,则礼正其经纬蹊径也。若挈裘领,诎五指而顿之,顺者不可胜数也。不道礼宪,以诗书为之,譬之犹以指测河也,以戈舂黍也,以锥餐壶也,不可以得之矣。故隆礼,虽未明,法士也;不隆礼,虽察辩,散儒也。

  问楛者,勿告也;告楛者,勿问也;说楛者,勿听也。有争气者,勿与辩也。故必由其道至,然后接之;非其道则避之。故礼恭,而后可与言道之方;辞顺,而后可与言道之理;色从而后可与言道之致。故未可与言而言,谓之傲;可与言而不言,谓之隐;不观气色而言,谓瞽。故君子不傲、不隐、不瞽,谨顺其身。诗曰:"匪交匪舒,天子所予。"此之谓也。

  百发失一,不足谓善射;千里蹞步不至,不足谓善御;伦类不通,仁义不一,不足谓善学。学也者,固学一之也。一出焉,一入焉,涂巷之人也;其善者少,不善者多,桀纣盗跖也;全之尽之,然后学者也。

君子知夫不全不粹之不足以为美也,故诵数以贯之,思索以通之,为其人以处之,除其害者以持养之。使目非是无欲见也,使耳非是无欲闻也,使口非是无欲言也,使心非是无欲虑也。及至其致好之也,目好之五色,耳好之五声,口好之五味,心利之有天下。是故权利不能倾也,群众不能移也,天下不能荡也。生乎由是,死乎由是,夫是之谓德操。德操然后能定,能定然后能应。能定能应,夫是之谓成人。天见其明,地见其光,君子贵其全也。

这里有译文:http://baike.baidu.com/subview/17130/5060547.htm?fr=aladdin

第一次OllyDbg逆向记录(分析思路和注意点&其他文章)的更多相关文章

  1. enode框架step by step之框架要实现的目标的分析思路剖析1

    enode框架step by step之框架要实现的目标的分析思路剖析1 enode框架系列step by step文章系列索引: 分享一个基于DDD以及事件驱动架构(EDA)的应用开发框架enode ...

  2. 32位汇编第六讲&comma;OllyDbg逆向植物大战僵尸&comma;快速定位阳光基址

    32位汇编第六讲,OllyDbg逆向植物大战僵尸,快速定位阳光基址 一丶基址,随机基址的理解 首先,全局变量的地址,我们都知道是固定的,是在PE文件中有保存的 但是高版本有了随机基址,那么要怎么解决这 ...

  3. so静态分析进阶练习——一个CreakeMe的分析思路

    i春秋作家:HAI_ 原文来自:https://bbs.ichunqiu.com/thread-41371-1-1.html 说明 拿到一个CreakeMe,写一个分析思路.CreakMe主要是对.s ...

  4. 多线程&lowbar;java多线程环境下栈信息分析思路

    导读:Java多线程开发给程序带来好处的同时,由于多线程程序导致的问题也越来越多,而且对问题的查找和分析解决对于菜鸟程序原来是是件头疼的事.下面我就项目中使用多线程开发程序过程中遇到的问题做详细的分析 ...

  5. Java应用性能瓶颈分析思路

    1 问题描述 因产品架构的复杂性,可能会导致性能问题的因素有很多.根据部署架构,大致的可以分为应用端瓶颈.数据库端瓶颈.环境瓶颈三大类.可以根据瓶颈的不同部位,选择相应的跟踪工具进行跟踪分析. 应用层 ...

  6. 逆向与分析-WebBrowserPassView消息分析

    逆向与分析-WebBrowserPassView消息分析 这个的源头是之前我写的一个博客: http://blog.csdn.net/u013761036/article/details/730427 ...

  7. 【jvm】09-full gc分析思路

    [jvm]09-full gc分析思路 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请顺手点个赞. ...

  8. CPU利用率异常的分析思路和方法交流探讨

    CPU利用率异常的分析思路和方法交流探讨在生产运行当中,经常会遇到CPU利用率异常或者不符合预期的情况,此时,往往暗示着系统性能问题.那么究竟是核心应用的问题?是监控工具的问题?还是系统.硬件.网络层 ...

  9. CrackME 2011 &num; 2 逆向练习解题思路

    CrackME 2011 # 2 逆向练习解题思路 做题背景: 从朋友那里得到一道逆向题名字叫package,作为小菜的我当然要看一看啦,这名字辨识度太低我就按照运行的名字改成CrackME 2011 ...

随机推荐

  1. db2 进程

    DB2 通用数据库进程全接触 Dwaine Snow, DB2 UDB 和 Informix IDS 产品经理, IBM 多伦多实验室 Dwaine Snow 是 DB2 UDB 分区数据库以及查询巡 ...

  2. jquery on&lpar;&rpar;动态绑定元素的的点击事件无反应的问题记录

    1.jquery使用版本:v2.0 2.重现代码: html <table class="table"> <thead> <tr> <th ...

  3. python的defaultdict

    defaultdict是dict的一个子类,接受一个工厂函数作为参数,当访问defaultdict中不存在的key时,会将工厂函数的返回值作为默认的value. class defaultdict(d ...

  4. hzoj 2301(莫比乌斯反演)

    题意 对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公 数. 思路: 与先前的那个相比,这次a,c并不一定 ...

  5. Android 5&period;1&period;1 源码目录结构

    点击打开链接 最近公司培训新同事,我负责整理一点关于android的基础知识,遥想当年,刚接触android,也是一头雾水, 啥都不懂,就是靠看文档和视频,对android有一个初步了解,然后就通过查 ...

  6. maven压缩js css

    maven压缩<plugin> <!-- YUI Compressor Maven压缩插件 --> <groupId>net.alchim31.maven</ ...

  7. 让overflow&colon;auto页面滚动条出现时不跳动

    今天看到一篇张鑫旭的文章,转载过来.https://www.zhangxinxu.com/wordpress/2015/01/css-page-scrollbar-toggle-center-no-j ...

  8. 深入探讨JavaScript如何实现深度复制(deep clone)

    在代码复用模式里面有一种叫做“复制属性模式”(copying properties pattern).谈到代码复用的时候,很有可能想到的是代码的继承性(inheritance),但重要的是要记住其最终 ...

  9. HDU2732一个让我debug了一晚上的题目

    思路都理解了,清晰了,就是代码不对,还是有些小地方自己注意不到,即使就在你的眼前也不易发现的那种 Description: 也是一个最大流的构图,没相出来,或者说想简单了也是标记点1 至 n * m是 ...

  10. curl&lowbar;init 接口

    <?php// +----------------------------------------------------------------------// | ThinkPHP [ WE ...