Win32汇编学习笔记01.环境配置

news/2025/1/4 14:57:05/文章来源:https://www.cnblogs.com/weiyuanzhang/p/18646475

Win32汇编学习笔记01.环境配置-C/C++基础-断点社区-专业的老牌游戏安全技术交流社区 - BpSend.net

环境配置

masm32下载

官网:http://www.masm32.com/

安装

img

成功标志

img

img

环境配置:

    • 将masm32下的bin目录添加到path
    • 新建include,将masm32目录下的inclcude目录添加进去
    • 新建lib,将masm32目录下的lib目录添加进去

img

测试代码
.386
.model flat, stdcall
option casemap:noneinclude windows.inc
include user32.incincludelib user32.lib.data
g_sz db "hello world", 0
.code
START:
invoke MessageBoxA, NULL, offset g_sz, NULL, MB_OK
end START

编译链接后可以生成可执行文件就带配置成功

img

编译链接:
1. 编译
ml /c /coff %1.asm(coff--PE)
ml默认⽣成的⽂件格式是16位的,通过 /coff 32位程序的可执⾏⽂件格式来指定32位的格式
2. 链接
link /subsystem:windows %1.obj
通过 /subsystem 来指定⼦系统, windows 是窗⼝程序, console 是控制台程序
编译脚本 build.bat:
@echo off
set include=D:\masm32\include
set lib=D:\masm32\lib
set path=D:\masm32\bin;D:\OllyICE_1.10del D:\OllyICE_1.10\udd\*.uddml /c /coff %1.asm
if errorlevel 1 goto errlink /subsystem:windows %1.obj
if errorlevel 1 goto errOllyICE.exe %1.exe:err

或者

ml /c /coff  %1.asmlink /subsystem:windows %1..objD:\OllyICE_1.10\OllyICE.exe %1.exepause
代码在scode高亮

img

img

16位与32位汇编的区别

1.源文件格式

  • 文件头固定三件套:

  • .386					; 表示使用的是386的是指令集
    .model flat, stdcall	; 指明内存模型和调用约定
    option casemap:NONE		; 其它选项,和ml或link的命令选项等价,32位汇编一般只用casemap-NONE
    
    • **msdn宏汇编官网:**https://docs.microsoft.com/en-us/cpp/assembler/masm/directives-reference?view=msvc-160
      • img
        • 8086和286都是16位的,从386开始是32位,后缀+P的指可以使用跳转指令的(适用于面向内核)。
      • img
      • casemap 最好只设 NONE 设all可能导致部分头文件没法用
      • img
    • 分段:32位汇编取消 了分段,改用内存属性来划分,称作节(section)、内存区或内存块。
      • 编写时每种类型可以定义多个,编译期会自动被同类归置

    img

.386					; 表示使用的是386的是指令集,最低版本,也可以用更高版本,常用386
.model flat, stdcall	; 指明内存模型和调用约定  只有c或者 stdcall
option casemap:NONE		; 其它选项,和ml或link的命令选项等价,32位汇编一般只用casemap-NONE.datag_sz db "hello world", 0
.datag_sz0 db "hello world", 0.data?g_sz dw ?.constg_sz1 db "test test", 0.codeSTART:
end START

寄存器

寄存器长度

img

32位 扩充了 8 个通用寄存器 和2个 ip 一次 flag 寄存器 , 扩充成了32位,, 低16位仍然保留原来的名字, 高16位没有名字,要访问需要自己移位 , 段寄存器没有扩充且其功能发生了改变

img

寄存器组

img

调试

32位汇编调试⼀般使⽤OD或者x64dbg,前者可以到看雪下载,后者可以到官⽹下载,两者建议都下

OD(OllICE)

目前只能调试32位程序

https://tool.pediy.com/ 看雪官网

img

img

解压密码: pediy.com

使用方式,

  1. 把 exe 文件拖进去
  2. 点击菜单

img

  1. 附近进程 : 调试正在运行的
  2. 右键用 ollyice 打开

img

img

鼠标点击有时候高亮不准是因此你改动了代码,但是软件保存了上次的调试信息,删除即可

删除上次调试保存的信息

  1. 删除该文件里面的文件

img

  1. 通过OD去删,删除要先退出调试,删完在重新调试,否则内存里仍然还有数据

img

X32Debug

可以调试64位程序

官网: https://x64dbg.com/

x32dbg 调32位 x64dbg 调 64位

调试快捷键

x32dbg 和 OD 的使用方式基本相同,包括快捷键

img

F4:运行到光标处。

esp: 回到栈顶

+/- 查看 下一步/上一步 运行的代码

菜单 查看断点可以查看所有的断点

指令补充

串操作现在支持一次四个字节的操作(26位只支持最高2字节)

  • 8086所有指令在32位保持原有功能不变,操作数长度扩充到32位。

img

movsx:高位补0,低位补1。

movzx:全部补0。

寻址

  • 相对于16位汇编,32位寻址的变化:
    • 1.在基址寻址和基址变址寻址两种寻址操作上面更加宽松:
      • 基址寄存器:通用寄存器都可用作基址寄存器;
      • 变址寄存器:除ESP外都可以用作变址寄存器。
      • *当基址为EBP或ESP时,访问的是栈上的数据。
    • 2.同时增加了比例因子寻址:变址寄存器 × 比例因子(1、2、4、8),便于遍历不同长度的数组。

img

.386
.model flat, stdcall
option casemap:NONEinclude windows.inc
include user32.inc
includelib user32.lib
.datag_szTitle db "hello world", 0 
.datag_sz db "hello world", 0 g_sz0 db "hello world", 0 g_ary dw 1111h,2222h,3333h,4444h,5555h
.data?g_dw dw ?
.constg_sz1 db "test test",0
.codeSTART:mov eax,offset g_aryxor ecx,ecxmov bx,[eax+ecx*type g_ary]inc ecxmov bx,[eax+ecx*type g_ary]inc ecxmov bx,[eax+ecx*type g_ary]inc ecxmov bx,[eax+ecx*type g_ary]mov eax,offset g_szmov ebx,offset g_sz0mov edx,offset g_sz1mov ecx,offset g_dwmov byte ptr [eax],'a'mov esi,1mov byte ptr [eax+esi],'b'mov edx,offset g_sz1mov byte ptr [edx+esi+1],'c';invoke MessageBoxA, NULL, offset g_szTitle, NULL, MB_OK
end START

调用API,弹MessageBox代码示例

.386                  ; 表示使用的是386的是指令集
.model flat, stdcall  ; 指明内存模型和调用约定
option casemap:NONE   ; 其它选项,和ml或link的命令选项等价,32位汇编一般只用casemap-NONEinclude windows.inc 
include user32.inc 
include kernel32.inc includelib user32.lib 
includelib kernel32.lib .datag_szText db "hello world", 0g_szTitle db "cr42 asm32", 0.code
START:invoke MessageBoxA, NULL, offset g_szText, offset g_szTitle, MB_OKinvoke ExitProcess, 0
end START

汇编版的第一个窗口

SDK 版弹窗

#include <windows.h>void ShowErrMsg();LRESULT CALLBACK CR42WindowProc(HWND hwnd,      // handle to windowUINT uMsg,      // message identifierWPARAM wParam,  // first message parameterLPARAM lParam   // second message parameter
)
{switch (uMsg){case WM_LBUTTONDOWN:{WORD wX = LOWORD(lParam);WORD xY = HIWORD(lParam);char szBuf[MAXBYTE] = {0};wsprintf(szBuf, "x:%d y:%d", wX, xY);MessageBox(hwnd, szBuf, NULL, MB_OK);return 0;}case WM_CLOSE:{int nRet = MessageBox(hwnd, "亲,是否要关闭窗口!", NULL, MB_OKCANCEL);if (nRet == IDOK){DestroyWindow(hwnd);//销毁窗口}return 0;}case WM_DESTROY://窗口已经被销毁PostQuitMessage(0);return 0;}return DefWindowProc(hwnd, uMsg, wParam, lParam); //自己不想处理的消息,交给系统默认处理即可
}int WINAPI WinMain(HINSTANCE hInstance,      // handle to current instanceHINSTANCE hPrevInstance,  // handle to previous instanceLPSTR lpCmdLine,          // command lineint nCmdShow              // show state
)
{WNDCLASS wc;wc.style = CS_HREDRAW | CS_VREDRAW;//窗口风格wc.lpfnWndProc = CR42WindowProc;//函数wc.cbClsExtra = 0;//窗口类对象额外内存大小,一般不用wc.cbWndExtra = 0;//窗口实例对象额外内存大小,一般不用wc.hInstance = hInstance;//实例句柄wc.hIcon = NULL;//没有图标wc.hCursor = NULL;//没有光标wc.hbrBackground = (HBRUSH)(COLOR_ACTIVEBORDER + 1);//背景颜色wc.lpszMenuName = NULL;//没有菜单wc.lpszClassName = "cr42 class";//窗口类的类名ATOM nRet = RegisterClass(&wc);if (nRet == 0){MessageBox(NULL, "注册窗口类失败!", NULL, MB_OK);return 0;}//wc.lpszClassName = "cr42 class2";//窗口类的类名//nRet = RegisterClass(&wc);//if (nRet == 0)//{//  ShowErrMsg();//}//DWORD dwErr = GetLastError();//创建窗口实例HWND hWnd = CreateWindow("cr42 class", //窗口类类名"我的第一个窗口",WS_OVERLAPPEDWINDOW,//重叠窗口CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,//坐标和尺寸大小NULL,//父窗口,没有NULL,//菜单,没有hInstance,NULL);//参数,暂时不用if (hWnd == NULL){ShowErrMsg();return 0;}//3 显示窗口ShowWindow(hWnd, SW_SHOW);//正常显示窗口//4. 更新窗口UpdateWindow(hWnd);// WM_MOUSEMOVE//WM_KEYDOWN//消息循环MSG msg;while (GetMessage(&msg, NULL, 0, 0)){//CR42WindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);DispatchMessage(&msg);}#if 0DWORD dw = CS_HREDRAW | CS_VREDRAW; //多种风格组合if (dw & CS_HREDRAW)//判断风格{}dw = dw & (~CS_HREDRAW); //取消风格#endif // 位运算在SDK中广泛应用return 0;
}void ShowErrMsg()
{LPVOID lpMsgBuf;FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_IGNORE_INSERTS,NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language(LPTSTR)&lpMsgBuf,0,NULL);// Process any inserts in lpMsgBuf.// ...// Display the string.MessageBox(NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);// Free the buffer.LocalFree(lpMsgBuf);
}

ASM32 版

查找变量定义 或者 函数的文件或库

img

 
.386 ; 表示使用的是386的是指令集 .model flat, stdcall ; 指明内存模型和调用约定 option casemap:NONE ; 其它选项,和ml或link的命令选项等价,32位汇编一般只用casemap-NONE include windows.inc include user32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib .data g_szClassName db "cr42asm32Class", 0 g_szTitle db "这个是我的第一个汇编窗口", 0 .code ; 过程函数 WindowProc PROC stdcall hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM .IF uMsg == WM_CLOSE invoke PostQuitMessage, 0 ;退出 .ENDIF invoke DefWindowProc, hWnd, uMsg, wParam, lParam ret WindowProc ENDP ;函数入口 WinMain Proc hInstance:HINSTANCE local @wc:WNDCLASS ;窗口类 local @hWnd:HWND ;窗口句柄 local @msg:MSG ;消息队列 ;sdk注册窗口类 ;WNDCLASS wc; ;wc.style = CS_HREDRAW | CS_VREDRAW;//窗口风格 ;wc.lpfnWndProc = CR42WindowProc; //函数 ;wc.cbClsExtra = 0; //窗口类对象额外内存大小,一般不用 ;wc.cbWndExtra = 0; //窗口实例对象额外内存大小,一般不用 ;wc.hInstance = hInstance; //实例句柄 ;wc.hIcon = NULL; //没有图标 ;wc.hCursor = NULL; //没有光标 ;wc.hbrBackground = (HBRUSH)(COLOR_ACTIVEBORDER + 1);//背景颜色 ;wc.lpszMenuName = NULL;//没有菜单 ;wc.lpszClassName = "cr42 class";//窗口类的类名 ;ATOM nRet = RegisterClass(&wc); ;if (nRet == 0) ;{ ; return 0; ;} ; 注册窗口类 mov @wc.style, CS_VREDRAW or CS_HREDRAW mov @wc.lpfnWndProc, offset WindowProc mov @wc.cbClsExtra,0 mov @wc.cbWndExtra, 0 push hInstance pop @wc.hInstance ;设置图标 invoke LoadIcon,NULL,IDI_APPLICATION mov @wc.hIcon,eax ;设置光标 invoke LoadCursor,NULL,IDC_ARROW mov @wc.hCursor,eax mov @wc.hbrBackground, COLOR_WINDOW+1 mov @wc.lpszMenuName,NULL mov @wc.lpszClassName, offset g_szClassName invoke RegisterClassA, addr @wc .IF eax == 0 ret .ENDIF ; HWND hWnd = CreateWindow("cr42 class", //窗口类类名 ; "我的第一个窗口", ; WS_OVERLAPPEDWINDOW,//重叠窗口 ; CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,//坐标和尺寸大小 ; NULL,//父窗口,没有 ; NULL,//菜单,没有 ; hInstance, ; NULL);//参数,暂时不用 ;if (hWnd == NULL) ;{ ; return 0; ;} ; 创建窗口示例 返回值 eax 窗口句柄 invoke CreateWindowExA, 0, offset g_szClassName, offset g_szTitle, WS_OVERLAPPEDWINDOW or WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT, NULL, NULL, hInstance, NULL .IF eax == NULL ret .ENDIF mov @hWnd,eax ;ShowWindow(hWnd, SW_SHOW); ;显示窗口 ;UpdateWindow(hWnd); ;更新窗口 ;显示窗口 invoke ShowWindow, @hWnd,SW_SHOW ;更新窗口 invoke UpdateWindow,@hWnd ;MSG msg; ;while (GetMessage(&msg, NULL, 0, 0)) ;{ ; TranslateMessage(&msg); ; DispatchMessage(&msg); ;} ; 消息循环 .WHILE TRUE invoke GetMessage, addr @msg, NULL, 0, 0 .IF eax == 0 .break .ENDIF invoke TranslateMessage, addr @msg invoke DispatchMessage, addr @msg .ENDW ret WinMain endp START: invoke GetModuleHandleA, NULL ;获取实例句柄 invoke WinMain, eax ;调用入口函数 invoke ExitProcess, 0 ;退出程序 end START 
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/862500.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM实战—7.如何模拟GC场景并阅读GC日志

大纲 1.动手模拟出频繁Young GC的场景 2.JVM的Young GC日志应该怎么看 3.代码模拟动态年龄判定规则进入老年代 4.代码模拟S区放不下部分进入老年代 5.JVM的Full GC日志应该怎么看 6.问题汇总1.动手模拟出频繁Young GC的场景 (1)程序的JVM参数示范 (2)如何打印出JVM GC日志 (3)示…

DI入门 -2025/1/1

applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://…

Leetcode刷题第三天-二分查找

力口二分查找162、167、209、240162. 寻找峰值 - 力扣(LeetCode) 没二分,数组头尾分别插入最小值和最大值,比较num[i-1]<num[i]>num[i+1]class Solution:def findPeakElement(self, nums: List[int]) -> int:if not nums:return Nonemax_num,min_num=min(nums)-1,…

linux系统变量配置与脚本

一、为什么要配置linux的环境变量 添加环境变量之后可以直接在 termianl 中运行 shell 脚本、 可以在 运行 界面直接运行 shell 脚本 可以为命令添加别名等操作,方便输入指令 可以添加函数,方便将常用组合写成一条命令,比如git的提交操作,经典的三条指令二、如何配置linux环…

linux系统变量配置

一、为什么要配置linux的环境变量 添加环境变量之后可以直接在 termianl 中运行 shell 脚本、 可以在 运行 界面直接运行 shell 脚本 可以为命令添加别名等操作,方便输入指令 可以添加函数,方便将常用组合写成一条命令,比如git的提交操作,经典的三条指令二、如何配置linux环…

BUUCTF Misc刷题37

37、[BJDCTF2020]你猜我是个啥 随波逐流梭了

Vue 使用脚手架

一、安装脚手架npm install -g @vue/cli注意:安装过程有警告,安装完后,关闭窗口,重新打开cmd,输入vue,没有报错 二、切换到创建文件的目录,然后使用命令创建vue create vue_test耐心等待 三、启动项目npm run serve

DL00237-基于YOLOv8深度学习的磁瓦缺陷检测含完整数据集实验结果

https://item.taobao.com/item.htm?ft=t&id=787390961923&spm=a21dvs.23580594.0.0.621e2c1bY0k4d9

中考英语优秀范文-005 What will you do for Mum? 你将为妈妈做些什么?

1 写作要求 天下最伟大的爱就是母爱。假设你是李静,母亲节就要到了,你们班将举办以What will you do for Mum? 为题的英语演讲比赛。请你准备一篇80词左右的演讲稿参加比赛。 2 优秀范文 What will you do for Mum? Hello, class. I’m Li Jing. Mother’s Day is coming. …

Notes.js的安装和配置

一、安装 1、下载 https://nodejs.org/en/download/ 2、安装 3、测试 打开cmd 查看node 和npm 版本node -vnpm -v 二、环境配置 1、找到安装目录,新建 node_cache 和 node_global文件夹 2、以管理员权限打开cmd 输入npm config set prefix "D:\nodejs\node_global"…

本地大模型初体验

前言 近几年这个话题很火,但是我一直没得去尝试一下,今天突然来兴趣想试试,然后就出来了这一篇文档。 环境准备docker安装管理工具 Ollama是一款开源的大模型管理工具,它允许用户在本地便捷地运行多种大型开源模型,包括清华大学的ChatGLM、阿里的千问以及Meta的llama等。目…