32位汇编第三讲,RadAsm,IDE的配置和使用,以及汇编代码注入方式

    32位汇编第三讲,RadAsm,IDE的配置和使用,以及汇编代码注入方式

一丶RadAsm的配置和使用

用了怎么长时间的命令行方式,我们发现了几个问题

1.没有代码提醒功能

2.编写代码很慢,记不住各种声明

那么现在有大神,已经帮我们做了一个IDE环境,就是RadAsm,首先简单介绍一下界面

(对于这个IDE(最新版是3.0)我已经打包好了,有中文版本,和英文版本)

我们需要配置一下环境

1.配置编译环境,配置lib文件库,配置Debug调试器

打开后会弹出

首先这里我们注意下面的几个选项

1.编译选项 Assemble : 这个是默认的即可,如果你是编译32位程序,那么我们就用 /c /coff 即可,后面几个默认

2.连接选项 link:  一般是默认的,他是默认生成windows的程序,如果我们有控制台的程序,那么我们可以手工去编译,

也可以通过它的项目,新建项目的时候选择指定的

3.扩展的调试器 External debugger: 这个则配置我们od所在的路径即可,3.0版本已经可以支持选择调试器了,以前的版本则是你指定文件夹,默认的调试器是Ollydbg.exe,所以我们名字还要改为这个才可以

4.library: 库的路径,有时候你编写汇编程序,会使用lib库,也会使用inc文件,那么可以把我们昨天的MASM32的库路径放到这里,也可以用高版本的,比如vc++6.0的,或者vs系列的都是可以的

注意:

  上面配置的编译选项,以及连接选项,我们都是安装的MASM32的,也就是昨天提供的工具,我们把它的路径设置为环境变量,这样就可以用编译的指令了,例如 /c /coff ....,如果你没有安装,或者没有配置环境变量,那么计算机就会找不到编译器,进而你的/c /coff就是错误的,所以一定注意要设置环境变量,如果不会环境变量的配置,请继续往下看,

如果会环境变量的配置,则直接跳到第二个标题, RadAsm的字体设置,以及中文乱码问题解决即可

环境变量配置,就是把你当前文件所在的路径,复制出来,放到计算机的path路径下即可.

这里我们拿QQ举个例子

1.首先我们CMD打开,然后输入qq.exe,他会找不到,例如:

2.如果想要让cmd找到我们的qq,那么就找到qq.exe所在的文件夹目录下,把路径复制一下,然后点击

计算机 -> 属性 -> 高级系统设置 -> 环境变量 -> (用户变量,或者系统变量),找到path(推荐使用系统变量)

把你的路径拷贝进去即可

①.找到qq所在的文件夹路径

②.打开文件位置

找到qq所在的文件路径

拷贝一下

③.打开计算机 -> 属性 ->高级 -> 环境变量

点击新建

输入刚才的路径

然后确定,然后打开 系统变量中的path

在后面加上 ;%QQ_HOME% 上一段话是以分号 ;结尾,所以我们加上分号

如果你不想这样弄也可以,直接分号,后面跟你刚才的QQ的路径即可,现在我们试下CMD是否能打开QQ

注意,配置完环境变量之后,需要重新打开CMD

然后大家就把昨天安装的Masm32的路径配置一下即可

2.RadAsm的字体设置,以及中文乱码问题解决

关于RadAsm的字体,以及中文乱码,网上有很多解决方法,这里我只对当前最新版本的RadAsm3.0做一个讲解

选择代码编辑

从上往下看

1.第一个红框,选择的是Masm的背景颜色,以及主题,这个可以自由设置不多做讲解

2.第二个红框,Tab Size 4,这里是编写汇编代码的时候Tab制表符,的距离,我们可以设置为2个

3.第三个红框,分别有个Code(代码按钮),和Line Number(行号的按钮)

这里则是设置代码字体的大小,还有行号显示的大小

首先中文乱码问题,打开code(代码编辑)

在这里设置代码字体的时候,一定注意要把下面的语言换成  ""中文 GB2312 " 而不是默西欧语言

选择了即可解决中文乱码的问题

三丶建立RadAsm工程,以及编译编译连接,和调试

1.打开 Project(项目) - > new Project(新建项目)

2.选择项目编译的语言,(这里我使用masm),选择项目生成的路径

默认即可

编写我们的第一段代码,并且调试输出

1,编译连接一起执行

,快捷键是Ctrl + F5

2.编译快捷键 是 F5

3.链接快捷键是 Ctrl + Alt + F5

4.调试快捷键是 Ctrl + D 它会默认打开我们的OD调试器,并且附加我们的程序,我们试一下

打开了我们的OD调试器,并且开始调试了

打开了我们的OD调试器,并且开始调试了

其余功能,自己尝试,如果不会配置,也可以在下方评论,那么我看到则会帮你解决,然后如果有好心人看到也会帮你一把

二丶汇编程序的注入代码,注入32位计算机,并且弹出个信息框

一丶远程线程注入的讲解

在讲解汇编程序注入代码的时候,我们需要先明白,远程线程注入的原理,我会写一个远程线程开发的例子,这样有助于我们理解汇编注入

我们总共需要几步

     /*1.查找窗口,获取窗口句柄*/

    /*2.根据窗口句柄,获得进程的PID*/

    /*3.根据进程的PID,获得进程的句柄*/

    /*4.根据进程的句柄,给进程申请额外内存空间*/

    /*5.调用WriteProcessMemory,给进程写入DLL的路径*/

    /*6.创建远程线程,执行我们的代码*/

    /*7.调用退出代码,释放远程线程的dll*/

每一步单独讲解

我们新建一个MFC 对话框程序,添加一个按钮,这个按钮专门响应注入的实现

第一步: 查找窗口,获得窗口句柄(采用WindowsAPI FindWindow,传入窗口名称,然后找到则返回对应的窗口句柄)

    HWND hWnd = FindWindow("","计算器");
    if(NULL == hWnd)
    {
        return;              //失败则返回
    }

第二步: 根据窗口句柄,查找进程PID (调用 GetWindowThreadProcessId API,传入窗口句柄,然后通过第二个参数把进程的PID给我们的参数)

  

  /*2.根据窗口句柄,获得进程的PID*/
    DWORD DwPid = 0;
    GetWindowThreadProcessId(hWnd,&DwPid); //这个函数会返回线程的ID,但是我们不关心,所以没有加返回值

第三步: 根据进程PID,返回进程的句柄(OpenProcess,参数一,权限 参数二,句柄是否继承,参数三,进程的pid)

 /*3.根据进程的PID,获得进程的句柄*/
    HANDLE hProHandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,DwPid);  //参数一,选择所有权限,参数二,不继承给false,参数三,给我们上面获得的pid的值
    if(NULL == hProHandle)
    {
        return;
    }

第四步: 给远程进程申请空间,并且返回空间的首地址(调用的API 是VirtualAllocEx)

/*4.根据进程的句柄,给进程申请额外内存空间*/
    LPVOID lpAddr = VirtualAllocEx(hProHandle,NULL,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
    if(NULL == lpAddr)
    {
        return ;
    }VirtualAllocEx说明:第一个参数: 进程的句柄第二个参数: 指定位置分配内存,给NULL为默认帮我们找块地方申请内存(不过这个地址会返回,所以不关心)第三个参数: 内存分配多大,我们给了4096个字节大小,也就是一个分页(1000H)第四个参数: 是否立即申请,还是保留这块内存,只能给我们用,但是还没申请,我们选择立即申请第五个参数: 权限,你申请的这块内存是什么内存,只能读,还是只能写,还是只能执行,我们选择全部,可读可写可执行

第五步:调用WriteProcessMemory将我们的Dll路径,写入到远程进程中

/*5.调用WriteProcessMemory,给进程写入DLL的路径*/
    char szBuf[MAX_PATH] = {NULL};
    GetCurrentDirectory(sizeof(szBuf),szBuf); //这三行代码主要是拼接我们的DLL,DLL是我们自己写的
    strcat(szBuf,"StaticDll.dll");       //DLL这里就不写了,用我的吧,我会发上去的
    BOOL bRet = WriteProcessMemory(hProHandle,lpAddr,szBuf,strlen(szBuf)+1,NULL);
    if(!bRet)
    {
        return;
    }WriteProcessMemory讲解:第一个参数: 进程的句柄,可以用我们上面的OpenProcess返回的第二个参数: 你要写入的地址,地址使我们VirtualAllocEx申请之后返回的(就是你要往哪个地址写内容)第三个参数: 你写入的内容是什么,写入的内容使我们的Dll路径,上面已经拼接好了第四个参数: 你写入的内容的大小是多大,这里我们用strlen求出来了第五个参数: 实际写入的个数,我们不关心,如果你想知道,则定义一个变量,然后 取地址传入即可,因为是个指针

第六步: 远程进程开辟线程,调用LoadLibrary,加载我们的dll,而你们知道,当dll被加载的时候,会有信息

所以我们在我们的dll里面写入我们自己的代码,比如这个dll被加载的时候,我们执行我们的代码,

这里我的代码就是找到计算器,然后给它加个菜单,并且响应消息

    HANDLE hThreadHandle = CreateRemoteThread(hProHandle,
        NULL,
        0,
        (LPTHREAD_START_ROUTINE)LoadLibrary,
        lpAddr,
        0,
        NULL);核心代码就在这里,我们必须要知道,我们现在加载我们的DLL,而我们的DLL被加载的时候,就要执行自己的代码所以这个时候就可以执行代码了CreateRemoteThread讲解:第一个参数: 进程的句柄(你要往哪个进程开辟线程)第二个参数: 安全属性,句柄可否继承,不需要给NULL第三个参数: 栈的大小,给0则默认第四个参数: 函数执行,我们要开辟线程,开辟的线程叫做loadLibrary第五个参数: 开辟线程传入的参数,我们知道,线程只有一个参数,而现在正好load也是一个参数,所以加载的参数就是我们的写入远程进程内存的dll路径,而dll路径一旦启动,则会执行自己的代码(核心,一定掌握)第六个参数: 创建的标志,默认给0第七个参数: 线程的ID,不需要知道,给NULL

我们尝试一下是否可以成功注入计算器,并且加入菜单

已经成功注入了.对于完整的代码,我会放到课堂资料中,但是这几步,一定要亲自手动弄明白

(备注: 我是使用VC++6.0编写代码,是MFC程序,当然你也可以用高版本,参考我这个,是一样的

对于DLL,我也会发,你们可以自己去写自己的DLL,比如一个空DLL会有DLL main,也就是dll的入口点

当第一次加载的时候会来信息什么的,所以可以在里面写代码.dll靠自己,这里只提供思路)

二丶汇编代码的注入

注意,别看博客每天内容很少,其实你想真正掌握,没有2-3个小时就不算掌握,当你真正明白这个知识点了,那才叫掌握,而不是看一遍就走的,自以为已经会了,千万不要眼高手低

比如上面的远程线程注入,原理是什么,虽然我代码给你了,当你知道原理了,那么代码自己就会写了

原理: 原理就是找到进程,利用VirtualAllocEX给他开辟个空间,利用他的返回值,会返回这个空间的地址

然后再利用WriteProcessMemory给这块空间写入DLL的路径,最后利用远程线程(CreateRemoteThread)

把loadlibrary当做线程回调执行,传入的参数就是远程进程空间我们写入的DLL路径,

这样相当于当另一个进程 调用了LoadLibray,并且加载我们的DLL,而利用DLL被加载会执行的机制,

然后在我们的DLL中写入被加载时候的代码即可.

(对于为什么我们确定loadlibary在远程进程中,其实这个是系统的特性,重要你软件一启动,就必然要有dll的支持

而我们调用的loadlibary就在这些dll中)

废话补多少,会的人请看今天重要的知识,汇编代码注入

首先,前边介绍了RadAsm的IDE环境,那么我们利用他建立一个Dlg汇编程序

1.首先,新建工程,创建一个窗口程序

(因为对于RadAsm3.0不太熟悉,所以这里不用3.0了,还是用2.2.2.0)

选择win32 app

选择 dialog app

生成的时候注意ID和窗口名

,对于ID,和IDname,我们需要自己去定义宏

然后在窗口过程函数相应我们的消息

注意,对于资源,我们必须单独编译,快捷键是 shift + F5

Ctrl + F5 编译运行

现在已经可以正常执行了

我们OD看一下,

Ctrl + D

下断点之后,消息来了,我们知道了WM_COMMAND消息是0x111,所以就直接调用MessageBox函数了

开始远程线程汇编代码的编写(因时间问题,今天只会讲解一个思路,具体的实现代码回去自己去写一下)

明天公布答案,以及坑

看汇编代码,我们会执行上面的那几个步骤

先把变量定义出来

  LOCAL @hWnd:HWND              ;查找窗口返回窗口句柄
  LOCAL @hProcessHandle:HANDLE: ;进程句柄
  LOCAL @dwPid:DWORD            ;进程的PID
  LOCAL @lpBuf:PVOID            ;远程进程开辟空间的首地址
  LOCAL @hThread:HANDLE         ;线程的句柄
  LOCAL @dwExitCode:DWORD       ;退出代码,获取的是远程load的返回值
                    ;这些变量都是定义在窗口过程函数中

第一步,判断按钮ID,并且查找窗口句柄

;1.解析低位,获得按钮消息,并且查找窗口句柄
    invoke FindWindow,NULL, offset g_szWindowName
    mov @hWnd,eax     ;把返回值给@hWnd
     .if eax == NULL
      ret
    .endif

第二步:获得进程的PID

invoke GetWindowThreadProcessId, @hWnd, addr @dwPID

第三步: 获得进程句柄

invoke OpenProcess,PROCESS_ALL_ACCESS, FALSE, @dwPID

  mov @hProcess, eax
  .if eax == NULL
   ret
  .endif

第四步:申请内存空间

invoke VirtualAllocEx,@hProcess, NULL, 1000h, MEM_COMMIT, PAGE_EXECUTE_READWRITE
        mov @lpBuff, eax
        .if eax == NULL
          invoke ShowLastError
          ret
        .endif

第五步: 直接写入代码,写入(按照以前,是往内存写入DLL路径,这里我们把代码写进去)

invoke WriteProcessMemory,@hProcess,
                                   @lpBuff,
                                   INJECT_CODE,         ;代码的标号
                                   start - INJECT_CODE,     ;起始位置-标号等于实际大小
                                   NULL

标号是写在代码区的上面的

一会OD调试一下看看

至于为什么写入的代码要ret 4,也就是start上面的那句话,是因为

下面我们调用CreateRemoteThread的时候,其中一个参数是@lpbuf,我们是当做函数调用的,所以压入一个返回地址

第六步: 创建远程线程

invoke CreateRemoteThread,@hProcess, NULL, 0, @lpBuf, NULL, 0, NULL
        mov @hThread, eax
        .if eax == NULL
          ret
        .endif

        invoke WaitForSingleObject,@hThread, INFINITE  等待结束
        invoke GetExitCodeThread, @hThread, addr @dwExitCode 获取loadlibrary的返回值他的返回值其实是dll在内存中的实例句柄,所以我们需要释放掉.(释放自己可以搜一下,暂时先把主要的讲了)

OD分析 明天讲解,今天先熟悉一下代码,内容比较多,消化一下

课堂资料:

  链接:http://pan.baidu.com/s/1o7B9f2i 密码:5kcu

时间: 2024-10-12 13:58:30

32位汇编第三讲,RadAsm,IDE的配置和使用,以及汇编代码注入方式的相关文章

win7下32位的JDK下载和环境变量配置

先在D盘下新建一个java文件夹,双击jdk应用程序,点击下一步,点击更改,将安装目录改为D:\java\jdk1.7.0_05\ , 2. 稍后会出现jre的安装,点击更改,将安装目录改为D:\java\jre7\ ,点击下一步, 点击继续,稍后将会出现javaFX的安装,点击取消即可,此时Java目录下有 3 安装完JDK后配置环境变量, 计算机→属性→高级系统设置→高级→环境变量, 在系统变量中新建变量: JAVA_HOME ,值:D:\java\jdk1.7.0_05 接着新建变量: C

Oracle 11g+oracle客户端(32位)+PL/SQL develepment的安装配置

之前一直想学Oracle,可是就是安装配置Oracle一直未成功,让人很苦恼,特别是什么监听器什么的,一直没搞明白,弄了整整一天都没弄出来,上网查资料后发现资料上大多数都是参差不齐,不太详细明了,尝试过后都未成功,现在通过我的精心调制,总算安装成功了,想与大家分享!   一.Oracle 11g数据库的安装   1.安装前的准备 安装文件下载地址:http://pan.baidu.com/s/1pJ5S2BT 将Oracle11g的两个文件解压到同一个目录下,出现如下结构:    点击setup

MongoDB step by step (一)Windows XP 32位安装mongodb及其目录结构和配置

MongoDB是一个提供高性能.高可用性.和自动伸缩的开源的文档数据库. MongoDB 是由 c++语言编写. 文档数据库(DocumentDatabase): 记录在MongoDB中称之为文档,它是列值成对的数据结构组件.MongoDB文档类似于JSON对象(呵呵,本人还不了解).列值可能包括其他文档.数组.或者文档中的数组.   更多有点和特征参考 Introductionto MongoDB:http://docs.mongodb.org/manual/core/introduction

win7 32位下 QT4.8.6 从安装配置到静态编译

  最近用QT编了一个很水的小程序,虽然之前用过QT但是编出来的程序都是在本机运行,本地的环境什么的当然配置好了能运行,但是拿到别的机子上就不行了,QT默认的编译方式是动态编译,即运行程序需要依赖QT动态链接库中的dll文件,如果想在别的电脑上运行你的程序,就需要把这些dll文件一起放到exe下一起带走,但是QT有几个动态链接库太大了一个就要上百兆,如果你的程序中需要用到这些dll文件中的东西,就需要一起带走,这样的话你做一个很小的程序最后需要运行的话足足要几百兆的空间,很是浪费.还好QT提供了

32位汇编第七讲,混合编程,内联汇编

32位汇编第七讲,混合编程 博客园IBinary原创 QQ:2510908331  博客连接:http://www.cnblogs.com/iBinary/ 转载请注明出处,谢谢 混合编程的概念,有时候我们会想,C语言可不可以调用汇编的函数,或者反过来调用 或者说C语言里面内部直接内联汇编去编写. 可以实现,静看怎么实现 一丶C语言调用汇编语言的函数 1.创建工程和代码 ①创建VC++控制台程序 FILE(文件) - NEW (新建) 然后我们打开源文件,一级一级展开,找到我们的main函数 那

汇编知识扫盲之16位汇编跟32位汇编的保护模式以及汇编代码编写

汇编知识扫盲之16位汇编跟32位汇编的保护模式以及汇编代码编写 一丶内存寻址模型 逻辑地址.线程地址.物理地址 了解汇编之前.先了解一下上面这些词的含义; 逻辑地址: 这个是邮编一起生成的.逻辑地址一般都是 段加段内偏移组成的.每个进程独享. 线性地址: 由分段管理机制.将逻辑地址转化为线性地址.这个了解即可.学过内核的人看到应该明白.如果没有学过.简单滤过即可(32位下逻辑 = 线性) 物理地址: 通过分页管理机制(内核中成为PDE PTE等页目录 页表等等)将线性地址转化为物理地址. 这些了

32位汇编第五讲,逆向实战干货,(OD)快速定位扫雷内存.

32位第五讲,逆向实战干货,快速定位扫雷内存. 首先,在逆向之前,大家先对OD有一个认识. 一丶OD的使用 标号1: 反汇编窗口 (显示代码的地址,二进制指令,汇编代码,注释) 标号2: 寄存器窗口(显示通用寄存器,段寄存器,以及浮点协处理器,32位中还有多媒体寄存器) 标号3: 信息窗口 (这个主要是显示当你运行到的程序的位置处的信息) 标号4: 数据窗口   (内存中的数据,可以在这里查看内存) 标号5:堆栈窗口 (查看栈中的内容,以及变量的内容) 标号6,标号7,标号8 ,属于工具窗口,不

32位汇编第四讲,干货分享,汇编注入的实现,以及快速定位调用API的数量(OD查看)

32位汇编第四讲,干货分享,汇编注入的实现,以及快速定位调用API的数量(OD查看) 昨天,大家可能都看了代码了,不知道昨天有没有在汇编代码的基础上,实现注入计算器. 如果没有,今天则会讲解,不过建议把昨天代码熟悉一遍(课程是紧跟着来的,请不要拉下任何一天,因为今天的知识, 可能就和昨天的知识挂钩,昨天的知识,和前天的挂钩.....,当然你如你懂汇编,不是新手,那么则可以直接往下看) 一丶远程线程注入,和汇编远程注入的区别 昨天的代码,大家可能看了(没看也没有关系,就是远程线程注入的代码,开发角

64位和32位的寄存器和汇编的比较

转载于http://blog.csdn.net/qq_29343201/article/details/51278798 64位(新增)汇编指令的不同 mov指令和push pop扩展了movq系列的mov和pushq以及popq用来操作quad word. 注意:movabsq不是32位的扩展,是纯新增的指令.用来将一个64位的字面值直接存到一个64位寄存器中.因为movq只能将32位的值存入,所以新增了这样一条指令. 顺带提一个小问题,64位的汇编代码在ret之前可能会加一句rep,这里的r