从2010\1\8开始,在这此帖整理自己的学习笔记:
1>2009\2\7就买到了《加密与解密》第三版,可到现在只会对无壳的软件暴破(太懒了!),自己都无颜了,再这样下去,怕是走不进逆向的世界了。
2>在此帖中得到无形的监督
3>相信也有雪友在学习中,希望能相互交流,共同进步。
故,开始《加》的学习。
----------------------------------------------开始-------------------------------------------------------------
某些RISC架构的CPU,eg:IBM的POWER-PC等为Big-Endian类(正序)
Big-Endian:高字节存入低地址,低字节存入高地址。(少见的情况)
Little-Endian:低字节存入低地址,高字节存入高地址。(这种是我们的机子的顺序)
所以当我们PEDIY时,就是用逆序存放的。
1.2什么是UNICODE?
额,区别于ASCII,大二学C时,总说“啊斯克码”,全称 美国信息交换标准码
American Standard Code for Information Interchange
Unicode是ASCII的扩展,eg:
70h 65h 64h 69h 79h(ASCII的“pediy”) 7位编码
0070h 0065h 0064h 0069h 0079h(Unicode的“pediy”) 16位编码
1.3什么是API?
额,我用了不少API了,应用程序编程接口(Application Programming Interface)
windows提供的丰富的API给程序员使用,这些API封装到DLL中。
系统最常用的DLL:
Kernel:16bit KRNL386.EXE + 32bit KERNEL32.DLL,包括进程与线程控制、内存管理、文件访问等核心功能服务
听名字就知道kernel--1.谷粒;仁,核2.要点,中心,核心
难怪,我们用OD时,经常一个CALL跑到系统领空,那就是到这些DLL中去了。
User:16bit USER.EXE + 32bit USER32.DLL,处理 键盘鼠标输入、窗口和菜单管理等用户接口。
GDI:16bit GDI.EXE + 32bit GDI32.DLL,这个也很常用,如我们用画直线画点等API。作用是 允许用户在屏幕和打印机上显示文本和图形。
英文是Graphics Device Interface图形设备接口。
以上三个几乎是用汇编写程序必用的DLL:
;--------include files-------- include gdi32.inc includelib gdi32.lib include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib ...
COMDLG32.DLL:通用对话框DLL。这个也相当常用了,
使用
打开文件对话框Comctl32.dll:标题栏、进度条、状态栏、滚动条、工具栏、提示文本、树型视图、列表视图等控件的相关API,都要用到这个库。
保存文件对话框
字体选择对话框
颜色选择对话框
查找和替换文本对话框
页面设置对话框
浏览目录对话框 等相关API,就要用到comdlg32.dll
wsock32.dll:网络编程接口库。对网络数据包的操作用到。
1.4 常用API函数
参考:MSDN或百度google或..
由于字符分ASCII和Unicode编码,所以一些与字符相关的API,就分成2类。
以A结尾(单字节方式)以W结尾(宽字节方式)
eg:
GetWindowText:获取窗口文本 GetWindowTextA/GetWindowTextW
GetDlgItemText:获取对话框文本 GetDlgItemTextA/GetDlgItemTextW
MessageBox:创建和显示信息框 MessageBoxA/MessageBoxW
我们写程序时,只用调用MessageBox就可以,编译器会根据设置来采用A/W。
[思考]但如果用OD对API下断点时,我们是对以A结尾的API下断 还是 对以W结尾的API下断呢?
我的想法是,先用Ctrl+N打开导入库,查看是什么样的API,再下断,就可以了。
当然,也可以先下A型的,不行,再下W型的。一次次试。
1.5 什么是句柄
句柄就是一个标识符,本质是一个整数。由于表示的东东的类型不同,分为:
窗口句柄
资源句柄(细分为 字符串句柄、声音wav资源句柄、图片句柄等等)
总之就是 一个用于保存每个东东的索引的DWORD型整数。比如:
1.6 windows各操作系统与Unicode的处理代码:;---------------------------------------------- ;EQU define ;---------------------------------------------- DLG_MAIN EQU 1000 对话框 ICO_MAIN EQU 100 程序图标 ;... ...s RED_TXT EQU 1001 Richedit控件 IDM_OPENFILE EQU 10002 以下都是菜单项的句柄 IDM_EXIT EQU 10003 IDM_BASICINFO EQU 10004 IDM_IMPORT EQU 10005 IDM_EXPORT EQU 10006 IDM_RESOURCE EQU 10007 IDM_RELOCATION EQU 10008 IDM_VERSION EQU 10009
ASCIId码只有7位,保存的信息少,而Unicode为16位,可以保存更多的信息,如我们的汉字就是2个UNICODE大小。
一、9x系统,即win95-win98(不是很严谨)的处理如下:
将UNICODE字符参数先转换成ASCII类型--->再调用ASCII型的API
eg:
windows98里MessageBoxW函数的内部定义 int MessageBoxW(MessageBoxExW{ // 调用MessageBoxExW()函数);WideCharToMultiByte(); // 取得要显示文本的长度 GlobalAlloc(); // 按字符串长度分配内存 WideCharToMultiByte(); // 将UNICODE文本转换成ANSI字符串 WideCharToMultiByte(); // 取得消息框标题文本的长度 GlobalAlloc(); // 按字符串长度分配内存 WideCharToMultiByte(); // 将UNICODE文本转换成ANSI字符串 MessageBoxExA(); // 最终还是调用ANSI版的MessageBoxExA();函数显示窗口 GlobalFree(); // 释放内存 GlobalFree(); // 释放内存}
二、NT/2000/XP系统如何处理Unicode
NT及以上系统好像完全反过来了。
将ASNI字符串先转换成UNICODE,再调用W型API,因为NT及以上系统是的系统核心完全是用Unicode函数工作的。
eg: int MessageBoxA( MessageBoxA{ // 调用MessageBoxExA()函数 MBToWCSEx(); // 将消息框主体文字转换成Unicode字符串 MBToWCSEx(); // 将消息框标题文字转换成Unicode字符串 MessageBoxExW() // 调用MessageBoxExW()函数 HeapFree() // 释放内存 } );
1.7 windows消息机制
[笑话一则]学到这里,我想起最近发生的事。是在QQ上和朋友聊天,朋友是学软件工程的,他居然不知道C可以写窗口程序,他理解为C只能写console这种黑框框的控制台程序。
并和他同学一致讨论,认为,C++才能写窗口程序!
我的理解是:只要在理解windows消息机制的基础上,调用相关API,就可以写出窗口程序。C当然可以写窗口,因为C可以调用相关API,我也写过不少了。再说,好多网络游戏,单机游戏就是用C写的,有名的拉莫斯的游戏引擎就是用C写的,额,说远了,打住,说回来。
这里总结 C语言 和汇编语言 的window消息机制
先写汇编的框架:>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
;-------------------------------------------------------- ;time:2009-11-3 13:46 ;author:lichsword ;function: ; ;-------------------------------------------------------- .386 .model flat,stdcall option casemap:none ;---------------------------------------------- ;include file define ;---------------------------------------------- include windows.inc include gdi32.inc includelib gdi32.lib include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib ;---------------------------------------------- ;EQU define ;---------------------------------------------- ICO_MAIN EQU 100 ;... ... ;---------------------------------------------- ;.data segment ;---------------------------------------------- .data? hInstance dd ? hWinMain dd ? hIconMain dd ? .data ;... ... .const szClassName db 'MyClassName',0 szCaptionName db 'My Window Caption',0 szText db '这是一个窗口的框架。',0 ;--------------------------------------------- ;.code segment ;--------------------------------------------- .code ;--------------------------------------------- ;Main Window's process ;--------------------------------------------- _ProcWinMain proc uses ebx edi esi hWnd,uMsg,wParam,lParam LOCAL @stPs:PAINTSTRUCT LOCAL @stRect:RECT LOCAL @hDc mov eax,uMsg ;------------------------------------------- .if eax==WM_PAINT invoke BeginPaint,hWnd,addr @stPs mov @hDc,eax invoke GetClientRect,hWnd,addr @stRect invoke DrawText,@hDc,addr szText,-1,addr @stRect,DT_SINGLELINE or DT_CENTER or DT_VCENTER invoke EndPaint,hWnd,addr @stPs ;-------------------------------- ;add your code here... ;-------------------------------- .elseif eax==WM_COMMAND ;-------------------------------- .elseif eax==WM_CREATE invoke SendMessage,hWnd,WM_SETICON,ICON_BIG,hIconMain .elseif eax==WM_CLOSE invoke DestroyWindow,hWinMain invoke PostQuitMessage,NULL .else invoke DefWindowProc,hWnd,uMsg,wParam,lParam ret .endif xor eax,eax ret _ProcWinMain endp ;--------------------------------------------- ;Main Window ;--------------------------------------------- _WinMain proc LOCAL @stWndClass:WNDCLASSEX LOCAL @stMsg:MSG invoke GetModuleHandle,NULL mov hInstance,eax invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass ;--------------------------------- ;注册窗口类 ;--------------------------------- invoke LoadCursor,0,IDC_ARROW mov @stWndClass.hCursor,eax invoke LoadIcon,hInstance,ICO_MAIN mov hIconMain,eax push hInstance pop @stWndClass.hInstance mov @stWndClass.cbSize,sizeof WNDCLASSEX mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW mov @stWndClass.lpfnWndProc,offset _ProcWinMain mov @stWndClass.hbrBackground,COLOR_WINDOW+1 mov @stWndClass.lpszClassName,offset szClassName invoke RegisterClassEx,addr @stWndClass ;--------------------------------- ;Create and show window ;--------------------------------- invoke CreateWindowEx,WS_EX_CLIENTEDGE,\ offset szClassName,offset szCaptionName,\ WS_OVERLAPPEDWINDOW,\ 100,100,600,400,\ NULL,NULL,hInstance,NULL mov hWinMain,eax;save handle of window invoke ShowWindow,hWinMain,SW_SHOWNORMAL;show window invoke UpdateWindow,hWinMain ;update window ;--------------------------------- ;message circle 消息循环 ;--------------------------------- .while TRUE invoke GetMessage,addr @stMsg,NULL,0,0 .break .if eax==0;when @stMsg = WM_QUIT , eax=0 invoke TranslateMessage,addr @stMsg invoke DispatchMessage,addr @stMsg .endw ret _WinMain endp ;------------------------------------------------- start: call _WinMain invoke ExitProcess,NULL end start
/*-------------------- include files define ----------------------------*/ #include<windows.h> #include<windowsx.h> #include<winuser.h> #include<stdio.h> /*-------------------- defines files ----------------------------------*/ #define WIN32_LEAN_AND_MEAN // 不使用MFC #define WINDOW_CLASS_NAME "WINCLASS" /*------------------- struct define ----------------------------*/ /* ------------------- funciton indentifier -----------------------------*/ /* ------------------- funcitons -----------------------------*/ LRESULT CALLBACK WindowProc(HWND hWnd, UINT stMsg, WPARAM wParam, LPARAM lParam) { /* 窗口进程回调函数 完成windows消息分支处理 */ PAINTSTRUCT stPs; HDC hDc; switch(stMsg) { case WM_CREATE: { /* 窗口初始化 */ return(0); }break; case WM_PAINT: { /* 客户区绘制 */ hDc=BeginPaint(hWnd,&stPs); EndPaint(hWnd,&stPs); }break; case WM_DESTROY: { /* 窗口摧毁 */ PostQuitMessage(0); return(0); }break; default: break; } // end switch // 处理其它系统默认消息 return (DefWindowProc(hWnd,stMsg,wParam,lParam)); } // end WindowPric int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdline,int nCmdShow) { WNDCLASSEX stWndClass; // 保存建立的窗口类 HWND hWnd; // 保存窗口句柄 MSG stMsg; // 保存消息结构 /* 清空结构 */ RtlZeroMemory(&stWndClass,sizeof stWndClass); /* 填充窗口类 */ stWndClass.cbSize =sizeof(WNDCLASSEX); // 类大小 stWndClass.style =CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; // 窗口属性 stWndClass.lpfnWndProc =WindowProc; // 窗口进程函数 stWndClass.hInstance =hInstance; // 窗口句柄 stWndClass.hIcon =LoadIcon(NULL,IDI_APPLICATION); // 窗口主图标 stWndClass.hCursor =LoadCursor(NULL,IDC_ARROW); // 光标 stWndClass.hbrBackground =(HBRUSH)GetStockObject(BLACK_BRUSH); // 客户区背景 stWndClass.lpszMenuName =NULL; // 菜单 stWndClass.lpszClassName =WINDOW_CLASS_NAME; // 窗口类名 /* 注册窗口类 */ if(! RegisterClassEx(&stWndClass)) return 0; /* 创建窗口 */ if(!(hWnd=CreateWindowEx( WS_EX_CLIENTEDGE, WINDOW_CLASS_NAME, "DataStruct Demo", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100,100, 600,400, NULL,NULL, hInstance, NULL))) { return 0; } ShowWindow(hWnd,SW_SHOWNORMAL); UpdateWindow(hWnd); /* 进入事件循环 */ while(TRUE) { GetMessage(&stMsg,NULL,0,0); if(stMsg.message==WM_QUIT) break; // 处理快捷键 TranslateMessage(&stMsg); // 消息转发给窗口回调函数 DispatchMessage(&stMsg); } // end while // 返回操作系统 return (stMsg.wParam); } // end WinMain
流程看框架就明白了,相关API只有几个。更具体的,可以参考 罗云彬的《win32汇编语言程序设计》第四章第2节 或《windows程序设计》一书 或者 就在我们论坛上找,一定会有相关帖子的。
1.8 保护模式
学到这里,我想起我为啥这么喜欢汇编语言的原因了。因为它是我觉得唯一称得上“能调戏程序的语言”,注意,不是“调试”是“调戏”。

本节核心:
离开电脑,活动一下。
- 应用程序是不会直接访问物理地址的;
- 虚拟内存管理器通过虚拟地址的访问请求,控制所有的物理内存访问;
- 每个应用程序都有相互独立的 4GB 寻址空间,不同应用程序的地址空间是隔离的;
- DLL程序没有自己的“私有”空间,它们总是被映射到其它应用程序的地址空间中,作为其它应用程序的一部分运行。因为如果DLL不和其他程序同属一个空间,应用程序就无法调用它。
从这章开始,就有事做了,开始准备学习使用我们的武器装备了。
第一个是OllyDbg,简称OD;Ring3级程序调试器
学习教程,推荐先看论坛的CCDbuger的OD系列精华教程:[INDENT]
传送门:
【原创】OllyDBG 入门系列(一)-认识OllyDBG
【原创】OllyDBG 入门系列(二)-字串参考
【原创】OllyDBG 入门系列(三)-函数参考
【原创】OllyDBG 入门系列(四)-内存断点
【原创】OllyDBG 入门系列(五)-消息断点及 RUN 跟踪
【原创】关于《OllyDBG 入门系列(五)-消息断点及 RUN 跟踪》的补充
【原创】OllyDBG 入门系列(七)-汇编功能