人多,问题多,帮人家解决问题就是提高自己
delphi群:
本群已满: 79598397
500人超群: 29803842
汇编反汇编群:
54876861
本人经济原因,开个淘宝了,请大家帮点击一下,加点流量,对您可能有帮助
点击查看1
个人网站,纯HTML
淋巴消炎贴官网
posted @
2009-02-01 13:45 小叶子 阅读(284) |
评论 (0) |
编辑 收藏
映像函数:
1.createfilemapping();创建映像
HANDLE CreateFileMapping(
HANDLE hFile, //物理文件句柄
LPSECURITY_ATTRIBUTES lpAttributes, //安全设置
DWORD flProtect, //保护设置
DWORD dwMaximumSizeHigh, //高位文件大小
DWORD dwMaximumSizeLow, //低位文件大小
LPCTSTR lpName //共享内存名称
);
2.openfilemapping();打开映像
HANDLE openfilemapping(访问类型,是否可继承,共享内存名称)
3.mapviewoffile();映射到本进程中
mapviewoffile(句柄,访问类型,0,0,映射字节)
4.unmapviewoffile()关闭映像
unmapviewoffile(mapviewoffile的句柄)
posted @
2010-01-21 19:49 小叶子 阅读(657) |
评论 (0) |
编辑 收藏
一.内核对象和地址空间
为了更好地理解本文后面的内容,在介绍内存映像文件之前我们先简单回顾一下Window
s中内核对象和地址空间的有关概念。在Windows中有各种内核对象,如事件、文件、进
程、旗语、互斥体等。内核对象是由系统内核分配管理的一段内存块,只有系统内核能
够直接访问这一段内核对象数据,而应用程序只能通过Windows提供的一系列函数按规定
的方式去操作这些内核对象。我们通过调用有关Windows API函数创建内核对象(这些函
数通常带有Create前缀)。当我们调用一个函数创建内核对象的时候,该函数通常返回
一个标识该对象的句柄(HANDLE)。我们把标识该内核对象的句柄传递给有关windows函数
,告诉系统去操作哪一个内核对象。内核对象属于系统内核而不是进程,内核对象可被
多个进程访问使用,也即可在多个进程间共享。每个内核对象自身有一个引用计数值,
它记录有多少进程使用该对象,当引用计数值为零时由系统负责销毁内核对象。在多个
进程间共享内核对象有三种方法:句柄继承、命名、句柄复制。在本文后面将要提到的
文件映像对象亦是内核对象。
在Windows中每一个进程都有自己私有的地址空间,对32位的进程来说地址空间的大小是
从0x00000000 到 0xFFFFFFFF共4GB范围。这个空间仅仅是内存地址的范围,而不是计算
机的物理存储RAM空间,因而又称为虚拟内存空间。使用某段虚拟内存空间需要经过保留
和提交两个过程,将物理存储分配映像到地址空间的该段区域上。物理存储不应理解为
RAM,实际上应理解为来自于磁盘上(通常为硬盘)的系统内存分页文件,在必要时(读
写访问时)其内容才会被系统写到RAM中或从RAM中写回来。磁盘上的这种系统内存分页
文件又称为虚拟内存。
二. 内存映像文件
几乎每个应用程序都要和文件打交道。比如,应用程序有时需要打开、读取、再关闭文
件;而有时需要打开文件,将数据读到一个缓冲区再写回到文件中另一个位置。通常实
现起来都显得有点繁琐。Microsoft Windows提供了满足这两方面要求的最佳解决途径:
内存映像文件。
象使用虚拟内存一样,使用内存映像文件同样需要经过保留和提交两个过程,首先在进
程内存空间保留一块区域,然后提交物理存储给这段区域。不同的是物理存储来自于磁
盘上的文件,而不是系统的分页文件。也即将磁盘上指定的数据文件作为虚拟内存,这
个实现过程被称为文件映像,可以将文件全部或部分映像到进程的地址空间中。文件映
像过以后,可以把文件映像的部分当作已全部被载入内存一样的去访问它,这时又称它
为内存映像文件。
内存映像文件通常有三个方面的应用:
1. 系统使用内存映像文件载入和执行.EXE和.DLL文件。一方面节省了系统分页文件空
间,另一方面缩短了加载应用程序开始执行所需的时间。
2. 使用内存映像文件访问磁盘上的数据文件。绕开对文件实行I/O操作和对文件内容的
缓冲,交由操作系统内核去完成。
3. 使用内存映像文件可以实现在多个进程间彼此共享数据。Windows提供了在进程间进
行数据通信的其它多种方法。但这些方法也是通过内存映像文件来实现的,所以内存映
像文件是实现进程间通信最有效率的方法。
三. 内存映像文件使用步骤
要使用内存映像文件,可以按以下步骤:
(1) 调用Windows API 函数CreateFile()创建或是打开一个文件,得到一个标识该文
件(内核对象)的句柄,它确定了哪一个磁盘文件将要作为内存映像文件。
(2) 将(1)中得到的文件对象句柄作为第一个参数调用Windows API 函数CreateFileM
apping()创建一个文件映像对象。通知系统该文件的大小及对该文件的访问方式,同
时也得到一个标识该文件映像对象的句柄。
(3) 将(2)中得到的文件映像对象句柄作为第一个参数调用Windows API 函数MapView
OfFile()通知系统映像文件全部或部分内容到进程的某一段地址空间,并将此段空间
首地址通过该函数返回。这一步也就是使用虚拟内存的保留和提交过程,此后就可以利
用此首地址实现对文件内容的读写了。
也可以不做第一步,直接从第二步开始,但这时要用INVALID_HANDLE_VALUE为参数作为
标识文件对象的句柄,这时系统以其分页文件作为内存映像文件而不用指定磁盘上的哪
一个磁盘文件。当你使用完内存映像文件后,需要做以下几步清除动作。
(1) 调用Windows API 函数UnmapViewOfFile(),通知系统释放文件映像对象在进程地
址空间中占用的区域。
(2) 调用Windows API 函数CloseHandle(),分别关闭文件映像对象和文件对象。
四. 内存映像文件应用举例
1.应用一 —— 系统加载.EXE和.DLL
当一个.EXE文件被载入准备运行时,系统要执行以下几步:
(1) 系统定位.EXE文件在磁盘的位置。
(2) 系统创建一个新的内核对象——进程。
(3) 系统为此进程创建其私有地址空间。
(4) 系统保留地址空间中足够大的一块区域容纳.EXE文件。而这块区域的基地址在.EXE
文件中有所指定,通常在0x00400000处。
(5) 系统记下支持这块区域的物理存储是.EXE文件,而不是在系统内存分页文件。
这之后系统访问.EXE文件有关信息项,确定所要载入哪些.DLL(动态连接库)文件。系
统调用LoadLibrary函数载入.DLL文件,执行类似上述(4)、(5)步的操作。
(1) 系统保留地址空间中足够大的一块区域容纳.DLL文件。同样其基地址在.DLL件中有
所指定。 Visual C++下制作DLL,默认情况下是 0x10000000处。
(2) 如果从该基地址开始的区域已被另一个.DLL或.EXE所占,或从该基地址开始的区域
不够大,系统将在地址空间寻找另一块区域,保留给.DLL文件。
(3) 系统记下支持这块区域的物理存储是在.DLL文件,而不是在系统内存分页文件。
在所有的.EXE和.DLL文件被映像到进程的地址空间中后,系统开始执行.EXE文件的入口
点代码。
2.应用二 —— 进程间共享数据
Windows的确提供了很多快速、方便的机制用于应用程序间共享数据和信息。这些机制包
括RPC、COM、OLE、DDE、WINDOWS消息(特别是WM_COPYDATA),剪贴板,管道,套节字
等等。然而在Windows中,同一台机器上多进程间共享数据最底层的机制是内存映像文件
。也就是说在同一台机器上,采用上述提到的方法实现进程间通信,最终全都是通过内
存映像文件分别实现各自特定的任务。因此使用内存映像文件是提高这类程序性能的一
种极好途径。
多进程间共享数据是通过将同一个文件映像对象的同一块区域映像到各进程地址空间中
来实现的。映像到在各个进程中的地址空间区域可能有所不同,但是各进程的这段区域
共享相同的物理存储分页文件,如图1所示。因此,当其中一个进程向文件映像对象的这
一区域写入数据时,其他进程在它们自身的地址空间中就能看到这一区域的变化。
让我们接着看系统加载.EXE启动一个应用程序这个例子。当启动一个程序时,系统调用
CreateFile函数打开磁盘上的.EXE文件。然后系统调用CreateFileMapping函数创建一个
文件映像对象,最后调用MapViewOfFileEx (用SEC_IMAGE 标志)将.EXE文件映像到进程
的地址空间中。此处用MapViewOfFileEx代替MapViewOfFile使文件映像到进程地址空间
中的首地址是存储在.EXE文件中指定的位置。然后系统创建进程的主线程,把此映像区
域可执行代码区的第一个字节的地址赋给线程的执行指针,然后让CPU开始执行代码。
如果用户执行同一个程序第二个实例时,系统会发现所要创建.EXE文件的文件映像对象
在内核中已经存在,因而不会再创建新的文件对象或文件映像对象。取而代之的是,系
统再次映像文件,这次是在新创建进程的地址空间中。可见系统同时映像同一个文件到
两个地址空间中。显然这更有效使用了内存,因为两个进程共享同一个包含正在执行代
码部分的物理存储文件。
象所有共享内核对象方法一样,可以使用句柄继承、命名、句柄复制三种方法在多个进
程间共享文件映像对象。下面列出了用命名方法共享内核对象,实现在两个进程间共享
数据的部分具体代码。用命名方法实现多个进程共享同一个文件映像对象时,所有进程
只需要对共享的文件映像对象使用完全相同的名称。
进程1:
//创建一个物理存储来自系统分页文件的文件映像对象,
//其大小为4 KB 命名为MMFSharedData.
s_hFileMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
PAGE_READWRITE, 0, 4 * 1024, TEXT("MMFSharedData"));
//将该对象内容全部映像到进程地址空间中
PVOID pView = MapViewOfFile(s_hFileMap,
FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
进程2:
// 打开名称为MMFSharedData 的文件映像对象
HANDLE hFileMapT = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE,
FALSE, TEXT("MMFSharedData"));
//将该对象内容全部映像到进程地址空间中
PVOID pView = MapViewOfFile(hFileMapT,
FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
这两个进程在其各自pView指针开始处4KB内容的物理存储来自同一个分页文件的同一段
区域,因而具有相同的内容,也即它们共享同一段数据。
posted @
2010-01-21 19:44 小叶子 阅读(3113) |
评论 (0) |
编辑 收藏
在Delphi中涉及到系统编程的方面毫无例外都要调用API函数,在ShellAPI.pas单元中有要用到的API函数的原型。
实战演练:
一.新建一个应用程序: File->New Applicaton,在uses后部分定义一个消息常量:
WM_NID=WM_USER+1000; 系统规定从WM_USER开始为用户自定义消息。
再定义过程
procedure WMNID(var msg:TMessage);message WM_NID;
二.定义一个全局变量: NotifyIcon:TNotifyIconData,NotifyIcon是非常重要的一个变量,整个程序基本上是围着这个变量在转。TNotifyIconData是一个记录类型,按住Ctrl键,在TNotifyIconData 双击即进入ShellAPI.pas单元。(注:在Delphi中,这是一个非常好的对源代码进行分析的方法,源代码说明一切,你要想知道程序背后的内幕,最好的方法就是分析源代码!)此时出现了以下赋值语句:
TNotifyIconData = TNotifyIconDataA,这个意思很明显,就是说TNotifyIconData和TNotifyIconDataA是同种数据类型,接着往下看有:TNotifyIconDataA = _NOTIFYICONDATAA,意思与刚才的一样,再往下看:
type
_NOTIFYICONDATAA = record
cbSize: DWORD;
Wnd: HWND;
uID: UINT;
uFlags: UINT;
uCallbackMessage: UINT;
hIcon: HICON;
szTip: array [0..63] of AnsiChar;
end;
这可真是“千呼万唤始出来,犹抱琵琶半遮面”。现在大家很清楚了,我们刚才定义的全局变量NotifyIcon其实是一个包含有7个成分的记录类型变量,就相当于C/C++中的结构体变量(C/C++的程序员应该是再熟悉不过了)。下面我们逐个来解释记录类型中的7个部分各有什么功能。
1> cbSize就是你定义的NotifyIcon变量的大小,用SizeOf(TNotifyIconData)可以取得,如果你是一个熟练的C/C++程序员,你应该不会陌生。在C/C++中,每当要为一个结构体变量分配内存的时候都要:通过 SizeOf(Struct type) 来获知存放一个这样的结构体变量要多少内存。
2> Wnd是一个句柄,你希望托盘程序产生的消息有哪个窗体来处理就让Wnd指向那个窗体。
例如:你准备在任务栏的托盘小图标上单击时窗体是窗体在“显示”和“隐藏”之间切换,则把Wnd指向主窗体。
3> uID:如果你要创建多个托盘小程序,那么怎么区分它们呢?就是靠这个ID号来区分。
3> uFlags是一个标志位,它表示当前所创建的托盘程序具有哪些性质:
NIF_ICON 表示当前所设置的图标(即hIcon的值)是有效的
NIF_MESSAGE 表示当前所设置的系统消息(即uCallBackMessage的值)是有效的
NIF_TIP 表示当前所设置的提示条(即szTip的值)是有效的。
4> uCallBackMessage这是7个部分里面最重要的一个。这里指定一个回调消息,也就是说这里定义一个消息名,当你单击或者右击托盘图标的时候就会向你在Wnd所指向的窗体发送一个你在
uCallBackMessage中定义的消息名,然后你在程序中定义一个消息出来函数来处理这个消息。这样就把Windows关于消息的整套流程都处理好了。
6> hIcon为托盘图标的句柄,根据这个句柄你就可以增加、修改、删除。
7> szTip就是当你的鼠标放到任务栏托盘的小图标上的时候弹出来的提示信息。
在这里我花了大量的笔墨介绍TNotifyIconData的内幕,把这部分搞清楚了,后面的东西就顺理成章了。
三. 双击主窗体,进入FormCreate的代码区域:
TForm1.FormCreate(Sender:TObject);
Begin
//NotifyIcon为全局变量,在程序的开头已经定义了
with NotifyIcon do
begin
cbSize:=SizeOf(TNotifyIconData);
Wnd:=Handle; //指向当前窗体Form1的句柄
uID:=1;
uFlags:=NIM_ICON or NIM_MESSAGE or NIM_TIP;
uCallBackMessage:=WM_NID;
hIcon:=Application.Icon.Handle;
szTip:=”张家恶少”;
end;.
//把设置好的变量NotifyIcon加入到系统中以便处理
Shell_NotifyIcon(NIM_ADD,@NotifyIcon);
End;
四.接下来就是定义一个消息处理函数:系统给窗体发来了一个消息,就由下面这个函数来处理。每个消息处理函数都是处理某一类消息的,大家仔细地看看下面函数体的定义和一般的函数定义有什么不一样:消息处理函数要在后面加上消息的名称,这样当系统发来WM_NID消息时,就是自动触发
WMNID消息处理函数。
procedure tform1.WMNID(var msg:TMessage);message WM_NID;
begin
case msg.LParam of
WM_LBUTTONUp; Form1.Visible:=not Form1.Visible;
WM_RBUTTONUP: ShowMessage(‘您点击的是右键’);
End;
End;
好了,一个最简单的程序诞生了,大家自己设置好自己喜欢的图标.
Project->Options,选中Application页面,在Icon项中加载自己喜欢的图标,这样程序运行时,在任务栏里显示的就是你喜欢的图标了。当你单击图标时,窗体Form1会在可见与不可见之间切换,也就是说单击一下显示,再单击一下又隐藏。当你右击图标的时候会弹出一条消息:“你点击的是右键”。
五.最后要记住在关闭应用程序的时候要释放掉建立的托盘程序,否则会占用系统资源。
TForm1.FormDestroy(Sender:TObject);
Begin
Shell_NotifyIcon(NIM_DELETE,@NotifyIcon);
End;
毕业快半年了,很多东西在学校总理解不了,认识不够深刻;出到社会,接触了不少道中朋友,受益非浅,每有心得体会,总想写成文字,一来总结自己学的东西,二来和大家共同交流。
//托盘图标是否显示
procedure HideSysTray(visible:boolean);
var
Tray, Child : hWnd;
C : array[0..127] of char;
S : string;
begin
Tray := FindWindow('Shell_TrayWnd', NIL);
Child := GetWindow(Tray, GW_CHILD);
While Child <> 0 do
begin
If GetClassName(Child, C, SizeOf(C)) > 0 Then
Begin
S := StrPAS(C);
If UpperCase(S) = 'TRAYNOTIFYWND' then
begin
If visible then ShowWindow(Child, 1)
else ShowWindow(Child, 0);
end;
end;
Child := GetWindow(Child, GW_HWNDNEXT);
end;
end;
当自定义过程 HideSysTray() 的参数为 False 时,托盘区隐藏,参数为 True 时,托盘区显示。
posted @
2010-01-20 20:25 小叶子 阅读(582) |
评论 (0) |
编辑 收藏
CALC
判断表达式
WATCH
添加监视表达式
AT
在指定地址进行反汇编
FOLLOW
跟随命令
orIG
反汇编于 EIP
DUMP
在指定地址进行转存
DA
转存为反汇编代码
DB
使用十六进制字节格式转存
DC
使用 ASCII 格式转存
DD
转存在堆栈格式
DU
转存在 UNICODE 格式
DW
使用十六进制字词格式转存
STK
前往堆栈中的地址
AS
(AS + 地址 + 字符串)
在指定地址进行汇编
BP
进行条件中断(有条件的断点)
BPX
中断在全部调用 (Call)
BPD
清除全部调用中的断点
BC
清除断点
MR
内存断点于访问时
MW
内存断点于写入时
MD
清除内存断点
HR
访问时进行硬件中断
HW
写入时进行硬件中断
HE
执行时进行硬件中断
HD
清除硬件断点
STOP
停止运行程序调试
PAUSE
暂停执行程序调试
RUN
运行程序进行调试
GE
运行和通过例外
SI
单步进入 Call 中
SO
步过 Call
TI
跟踪进入直到地址
TO
跟踪步过直到地址
TC
跟踪进入直到满足条件
TOC
跟踪步过直到满足条件
TR
运行直到返回
TU
运行直到用户代码
LOG
查看记录窗口
MOD
查看模块窗口
MEM
查看内存窗口
CPU
查看 CPU 窗口
CS
查看 Call 堆栈
BRK
查看断点窗口
OPT
打开选项设置窗口
EXIT
退出 OllyDbg
QUIT
退出 OllyDbg
OPEN
打开一个可执行文件
CLOSE
关闭可执行文件
RST
重新运行当前程序
HELP
查看 API 函数的帮助
posted @
2009-06-30 10:59 小叶子 阅读(1225) |
评论 (0) |
编辑 收藏
入口特征............
Microsoft Visual C++ 6.000496EB8 >/$ 55 PUSH EBP ; (初始 cpu 选择)
00496EB9 |. 8BEC MOV EBP,ESP
00496EBB |. 6A FF PUSH -1
00496EBD |. 68 40375600 PUSH Dumped.00563740
00496EC2 |. 68 8CC74900 PUSH Dumped.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.000401166 - FF25 6C104000 JMP DWORD PTR DS:[<&MSVBVM60.#100>] ; MSVBVM60.ThunRTMain
0040116C > 68 147C4000 PUSH Dumped.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
VB还有一种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
Borland C++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.000509CB0 > $ 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,Dumped.00509720
00509CC3 . E8 84CCEFFF CALL Dumped.0040694C
易语言入口00401000 > E8 06000000 call Dumped.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 Dumped.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 Dumped.004062F0
0040383B |. 68 A44C4000 PUSH Dumped.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 / TASM3200401258 >/$ 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 Dumped.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
VC8004A2ADC > $ E8 B6A40000 call Dumped.004ACF97
004A2AE1 .^ E9 16FEFFFF jmp Dumped.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 Dumped.004A2B20
004A2AFC |> 8A01 /mov al,byte ptr ds:[ecx]
004A2AFE |. 83C1 01 |add ecx,1
posted @
2009-06-20 13:48 小叶子 阅读(1856) |
评论 (0) |
编辑 收藏
一. INT3断点
一般用F2设置
可以设置无数个,但改变程序指令(68->CC)
很多程序都用检测函数前两个字节来检测自己是否被下断.解决办法是在函数前或后设置
二.硬件断点
他与DRx调试器有关,CPU共8个调试寄存器,从DR0-DR7
硬件断点就是利用DR0-DR3.这四个下断
右键->断点->硬件执行
三.内存断点
INT3不能用.硬件断点失灵里可用这个代替,程序没有跑起来时用
四.内存访问一次性内存断点
ALT+M->F2
五.消息断点
所有的消息都有四个参数: 窗口句柄 消息编号 两个32位数
六.条件断点
1 寄存器条件 eax==0400000
command里输入:bp 401776 eax==400000
2 按存储器条件
posted @
2009-06-10 14:54 小叶子 阅读(2172) |
评论 (0) |
编辑 收藏
在实模式下,CPU寻址方式:CS:偏移量
而保护模式下段寄存器放的是段选择子(既一个指针,段选择子长16位,其格式如下表所示。从表中可见,段选择子的高13位是描述符索引(Index)。所谓描述符索引是指描述符在描述符表中的序号。段选择子的第2位是引用描述符表指示位,标记为TI(Table Indicator),TI=0指示从全局描述符表GDT中读取描述符;TI=1指示从局部描述符表LDT中读取描述符) 选择子 + 偏移量指向了内存
现在说虚拟内存是怎么实现的?
1.应用程序被启动,系统创建一个进程,并分给它2GB虚拟地址(不是内存,地址而已)
2.虚拟内存管理器把程序代码映射到上面分配的2GB虚拟地址中,这里全部分配,程序运行时用到的代码再映射到物理内存中
3.如果程序用到dll,也被映射到另个2GB虚拟地址,真正用到时映射到物理内存(和1中的2GB共4GB)
.....
.....
上面是主要的。我比做一个例子也许好明白点:
一张桌子比做内存,周围的小朋友要在上面玩积木(一个人是一个程序)。
小张要先玩,从老师(硬盘)那里要来积木,放在口袋里,口袋就是2GB虚拟地址,全部在口袋里,如果他要用哪一块积木就放在桌子上,这就是映射到内存,用一点映射一点
小李也要玩,同小张一样
......
虚拟地址(每个人的口袋)解决了内存(桌子)不够用的问题。如果没有这个口袋,两个人玩时就可能把桌子全占了
posted @
2009-06-08 16:22 小叶子 阅读(844) |
评论 (1) |
编辑 收藏
getwindowtext()
getdlgitem()
getdlgitemtext()
windows消息机制用到的API
sendmessage()
WM_command 0111H (对应16进制数)
WM_destory 02H
WM_gettext 0DH
WM_quit 012H
WM_lbuttondown 0201H
posted @
2009-06-08 15:10 小叶子 阅读(561) |
评论 (0) |
编辑 收藏