这几天在重看SEH机制,收获颇丰。

随手写了一个用SEH进行跳转的代码贴于此处以作纪念。

当发生异常,并捕捉了异常。在OS的异常处理机制下。会进入异常过滤函数。

过滤函数能够返回EXCEPTION_EXECUTE_HANDLER/EXCEPTION_CONTINUE_SEARCH/EXCEPTION_CONTINUE_EXECUTION三者之中的一个,以此决定OS的兴许操作。

假设返回EXCEPTION_CONTINUE_EXECUTION。OS觉得异常已解决,能够从发生异常的指令处继续执行。一般这是用于解决訪问内存出错的情况。比方:

int* ptr=NULL;

int ex(EXCEPTION_POINTERS* ExceptionInfo)
{
ExceptionInfo->ContextRecord->Eax=(DWORD)malloc(sizeof(int));
return EXCEPTION_CONTINUE_EXECUTION;
} int main()
{
__try
{
*ptr = 0x00;
//004010AC   mov         eax,[ptr (00422780)]
//004010B1   mov         dword ptr [eax],0
 MessageBox(NULL,"","",MB_OK);
}
__except(ex(GetExceptionInformation()))
{ }
}

当运行*ptr=0x00时,因为ptr指向空。因此mov dword ptr [eax],0这句会引起异常。为了让代码继续往下运行弹出对话框。仅仅要让eax指向有效内存就可以。那怎样让eax指向有效地址?仅仅要给eax创建堆内存就可以,因此能够在异常过滤函数中开辟空间。按windows的设计。异常发生时OS会把压入在堆栈中寄存器值保存到线程环境中(通过KiTrapFrameToContext);当从异常返回时,用保存的线程环境恢复寄存器继续运行(通过KiContextToTrapFrame)。

那么所谓的线程环境在哪?代码中ExceptionInfo->ContextRecord即为所求。

因此,我在过滤函数中改动Context->Eax。使之指向有效内存,实现了修复异常继续指令流的目的。

事实上,这整个流程类似于SetThreadContext/GetThreadContext。

另外。值得一提的是,当异常发生时,假设异常类型是訪存失败,错误码是0xC0000005的情况下。

ExceptionInfo->ExceptionRecord->NumberParameters;

ExceptionInfo->ExceptionRecord->ExceptionAddress;

    ExceptionInfo->ExceptionRecord->ExceptionInformation[1];

这几个域包括了重要信息。

来看个常见而又蛋痛的对话框:

当你happy的玩着游戏时。跳出这个。是不是都毁了?假设细致看出错信息上面给出了例如以下信息:出错的指令的地址-0x6F001080,出错的原因-0xC0000005(訪问无效内存),无效内存的地址0xE2AF524C。

这些信息,进入内核态以后能够轻松获得,可是用户态有没有办法获得?比方想做一个用户态的调试器?当然有。上面提到的3个域依次相应:异常时ExceptionInformation数组的元素数量、出错的指令的地址、訪问无效内存的地址。

有了这些辅助信息后,開始讨论正题。事实上,这里已经呼之欲出了:代码混淆一般就是通过各种手段混乱代码运行流程,放在这篇文章中。仅仅要改动EXCEPTION_CONTINUE_EXECUTION返回时的地址就可以(注意我的用词,是EXCEPTION_CONTINUE_EXECUTION的返回地址,不是异常的返回地址,假设没记错对于vc++6.0异常的返回地址应该是_except_handle3)。进一步说,就是触发异常并保存线程环境时Eip的值。

罗列一下代码:代码运行流程为1)-5)

#include <windows.h>
#include <stdio.h> int* ptr;
//4)Msg被调用
void Msg(int a,int b)
{
int c = a+b;
printf("%d\n",c);
MessageBox(NULL,"","",MB_OK);
__asm
{
mov eax,c
}
} int ex(EXCEPTION_POINTERS* ExceptionInfo)
{
//3)准备跳转到Msg中
//Msg是带參数函数,參数保存在异常发生前的堆栈上。即Esp指向
//此时ExceptionInfo->ContextRecord->Eip[0]指向Lab1代表的地址
//ExceptionInfo->ContextRecord->Eip[4]=0x01 ExceptionInfo->ContextRecord->Eip[8]=0x02
ExceptionInfo->ContextRecord->Eip = (DWORD)Msg;
return EXCEPTION_CONTINUE_EXECUTION;
} int main()
{
int i=0;
ptr = (int*)&main;
__try
{
/*
原本向jmp Lab2,结果提示"illegal jump into __try scope",就这么取代一下
*/
if(1)
goto Lab2;
Lab1:
//5)从Msg返回后 指令流进入Lab1
i++;
printf("%d\n",i);
ExitProcess(0);
Lab2:
__asm
{
//1)制造Msg函数的參数及返回地址.模拟c调用函数的过程.异常触发后要跳入Msg运行
//对于Msg函数。他根本不知道是谁调用他的,他仅仅关心參数是否正确
push 0x02;
push 0x01;
lea eax,Lab1;
push eax;
}
//2)触发异常。给与Lab1中真正须要运行的代码于机会
(*ptr) = 0x01; }
__except(ex(GetExceptionInformation()))
{}
return 0;
}

利用SEH进行代码混淆的更多相关文章

  1. 在 NetBeans 中开发一般 Java 应用程序时配置 Allatori 进行代码混淆

    要在 NetBeans 中开发一般 Java 应用程序时利用 Allatori 进行代码混淆,设置比 IntelliJ IDEA 稍微简单一点,首先在 NetBeans 项目所在硬盘目录内创建一个名为 ...

  2. 利用proguard对java web工程代码混淆

    目标: 将代码混淆,也就是给第三方源代码,让他们只能运行,却看不懂代码. 用到的工具: 混淆jar的工具:proguard5.1 下载地址:http://download.csdn.net/detai ...

  3. Windows x86 下的 静态代码混淆

    0x00  前言 静态反汇编之王,毫无疑问就是Ida pro,大大降低了反汇编工作的门槛,尤其是出色的“F5插件”Hex-Rays可以将汇编代码还原成类似于C语言的伪代码,大大提高了可读性.但个人觉得 ...

  4. ProGuard代码混淆技术详解

    前言     受<APP研发录>启发,里面讲到一名Android程序员,在工作一段时间后,会感觉到迷茫,想进阶的话接下去是看Android系统源码呢,还是每天继续做应用,毕竟每天都是画UI ...

  5. iOS安全攻防(二十三):Objective-C代码混淆

    iOS安全攻防(二十三):Objective-C代码混淆 class-dump能够非常方便的导出程序头文件,不仅让攻击者了解了程序结构方便逆向,还让着急赶进度时写出的欠完好的程序给同行留下笑柄. 所以 ...

  6. Android 4.0 ProGuard 代码混淆 以及 proguard returned with error code 1.See console异常的解决方法

    最近呢说要上线,就去找了下上线的方法...之前做过代码混淆,用的是progarud.cfg,但是呢自己反编译了之后还是无效,然后就丢着先不管了,因为实在不知道什么情况.今天来上线的时候结果总是报错,总 ...

  7. iOS安全攻防之代码混淆

    iOS 代码安全之代码混淆实践: 前言: 在8月份的时候写了个关于 class-dump 反编译的文章(使用 Class-dump 反编译),利用 class-dump 工具可以反编译出工程的头文件, ...

  8. iOS 代码混淆

    一般做了防调试的话,被调试进程会退出的,是防动态分析措施. 代码混淆加花这些是防静态分析措施. 反调试是防动态分析措施. 混淆的方法方法名混淆其实就是字符串替换,有2个方法可以,一个是#define, ...

  9. 代码混淆工具——Virbox Protector Standalone

    VirboxProtector Standalone 加壳工具可对代码加密的技术有:代码混淆.代码虚拟化.代码加密. 代码混淆:利用花指令和代码非等价变形等技术,将程序的代码,转换成一种功能上等价,但 ...

随机推荐

  1. must have same number of columns as the referenced primary key

    在使用Hibernate实现多对多的测试过程中遇到了这个问题 解决的方法: 将黄色字段的内容添加进去 <set name="customerSet" table=" ...

  2. jdk11 eclipse下开启ZGC

    平台支持 ZGC目前只在Linux/x64上可用,如果有足够的需求,将来可能会增加对其他平台的支持. 对的,目前只支持64位的linux系统. -_-' eclipse.ini配置: -XX:+Unl ...

  3. [驱动] 一个简单内核驱动,通过qemu调试(1)

    模块 通过在HOST上修改linux kernel源代码,重新编译一个vmlinux,然后,通过qemu根据这个bzImage 启动一个vm,进行调试 #cat drivers/char/test.c ...

  4. mysql安装及navicat连接

    1.下载mysql官方连接:https://dev.mysql.com/downloads/mysql/ 下载成功后,解压到自己想要的路径下并创建my.ini文件和配置环境变量 然后我们在根目录下创建 ...

  5. SQL表变量与临时表区别 + 非游标临时表遍历

    SQL表变量与临时表区别 + 非游标临时表遍历 分类: SQL Server2009-11-27 17:01 1196人阅读 评论(2) 收藏 举报 sqlinsert存储sql servermicr ...

  6. 阿里云部署flask

    https://www.cnblogs.com/Ray-liang/p/4173923.html

  7. vue 接口统一管理

    在外部创建一个API文件夹,然后创建一个API.js  例如 const filmbanner = 'api/billboard/home?__t=1498823077473'; const film ...

  8. java常见日期格式转换以及日期的获取

    package com.test.TestBoot.SingleModel;import java.text.SimpleDateFormat;import java.util.Date;public ...

  9. PHP读取超大的excel文件数据的方案

    场景和痛点 说明 今天因为一个老同学找我,说自己公司的物流业务都是现在用excel处理,按月因为数据量大,一个excel差不多有百万数据,文件有接近100M,打开和搜索就相当的慢 联想到场景:要导入数 ...

  10. UVaLive 4868 Palindrometer (暴力 / 构造)

    题意: 给定一个固定长度的字符串, 字符串是一个含有前导0的数字, 问这个数字加上多少能构成一个回文字符串. 分析: 其实这题有很多种方法, 方法12是我做完后看别人代码总结的, 方法3是我当时想的一 ...