13

VT调试BluePill的心得

VT虽然已经流行多年,但是因为参考资料较少,所以研究起来有很多困难。

要学习VT,最好的参考资料之一就是NewBluePill源代码,该代码是Invisible Things Lab在2007年公开的,实现了一个基本的VMM,并加入了内存隐藏技术。阅读nbp的代码,并结合Intel开发手册作为参考,可以学习到Intel-Vt的方方面面。

因为最近在学校做一个项目,要用VT实现一些功能,所以我开始研究nbp的代码,期间遇到很多问题,困扰了我很久,经过N次BSOD后终于算是勉强把nbp弄明白了。在这里跟大家分享一下经验。

一.搭建调试环境

我搜索了论坛里有关VT调试的帖子,综合了网上的各种说法,普遍认为调试VT有3种方法:
1.Windbg+bochs虚拟机
好处是可以用我们熟悉的windbg
缺点是需要手工修改一些代码并重新编译bochs,很难自己装系统(因为太慢了),最后系统跑起来也感觉特别脆,容易出错,我试了很久好像也没弄好

2.IDA+GDB+bochs
不清楚,因为我一点也不了解GDB,而且我的IDA版本好像有问题,跟bochs配合也是个蛋疼的事情

3.两个物理主机通过COM连线,进行双机调试
我有两台机器,一个台式机(有COM口),一个笔记本(没COM,使用USB转COM插头),然后买了个母对母的COM连接线(因为我两个机器端都是公头),连好后却怎么也通讯不了,也不知道问题在哪,感觉特别无奈。。后来某次跟一个做嵌入式的同学聊了聊,他说可能是因为COM线的RXD引脚和TXD引脚需要交叉接,然后就帮我焊了个小板子,回去一试还真行了

这个方法好处是可以用windbg,而且不

[……]阅读全文

28

Qt GUI开发学习笔记

最早的时候喜欢用VB6写界面,因为非常方便,上手特别快。不过这也容易造就很多问题,而且时至今日,VB6已经太老了,项目开发也很少用VB甚至很少用BASIC语言,C/C++/Java成了主流。学C/C++的时候基本都是在控制台下做实验,没怎么涉及图形界面,不过真的到要用GUI的时候又发现自己什么都不会。后来,了解了Qt这个东西,它支持纯粹的C++语言(不像.NET的C++编程方式,有很多是自定义的特性),跨平台,构建界面也很方便,而且Qt是在持续更新的,不会很快就过时,于是决定要研究一下Qt。在这里贴出学习过程中的一些笔记,方便以后自己查阅,也给同样学习Qt的同学一些参考。

 

开发环境与工程结构

安装VisualStudio-Add-In后可以用VC结合Qt Designer进行开发,在VC里写代码,Qt Designer上画界面。

不过VC新建工程后要更改项目配置,在文件查找路径里添加上Qt的头文件、库文件等的所在路径,不然编译时会提示找不到文件。

对于每个窗体,Qt Designer会生成ui_frmName.h文件,其中包括class Ui_frmName的声明,用来描述用户在此窗口上设置的属性和添加的控件等信息。并且会在namespace UI里声明class frmName: public Ui_frmName {};

每个窗口类class frmNameClass都继承自QMainWindow或QDialog,并声明私有成员Ui::frmName ui_frmName用来控制显示窗口及控件(Ui::frmName即来自上面提到的Qt Designer生成的ui_frmName.h文件,一般地,用户不需要更改

[……]阅读全文

16

[调试笔记]x86页式内存管理(NOPAE)

这两天看了下x86内存分页机制,调试之后大概弄懂了,发出来做个笔记。

0.测试代码

ULONG TestVar = 123456;   // Global Variable
KdPrint(("VirtualAddress: %X\nPhysicalAddress: %X", &TestVar, PhyAddress));   // in DriverEntry

WINDBG输出如下

00000003    35.10139084    VirtualAddress: F889B000    
00000004    35.10139084    PhysicalAddress: 338A000

 

1.物理内存定位
DirBase=CR3,保存着当前进程的页目录表基址

lkd> dd F889B000
f889b000  0001e240 f8891597 0776ea68 00000000
f889b010  00000000 00000000 00000000 00000000
f889b020  00000000 00000000 00000000 00000000
f889b030  00000000 00000000 00000000 00000000
f889b040 

[……]阅读全文

31

WDK驱动开发使用C++模板实现动态存储类CLinkList

WDK支持C++编译,但大多数人写驱动还是习惯用纯C甚至C/C++滥用…最近写一个小项目,驱动代码我则尝试了完全使用C++来实现,之后我发现,即便是驱动开发,C++也要比纯C语言方便得多。虽然内核里没有STL,但是WDK仍支持C++的很多特性,类、重载、模板,以及多态的很多特性,都可以正常使用(当然..我也只是个C++初学者,很多高级功能并没有尝试)。

在内核编程时,很多时候我们要遍历一些内核里的数据结构并做记录,而这些数据的大小通常是动态的,我们在开始遍历时并不知道储存他们的记录要占用多大空间。面对这种问题,最简单的有两个解决方法:

1.分配一个足够大的内存,保证能存储下数据(大多数情况下会浪费很多空间)

2.预先遍历一遍并记录总大小,然后再遍历一次进行记录(毫无疑问地效率低)

以上两种简单的方法都有不可忽视的缺陷,所以我们要用稍高级一些的数据结构来解决这个问题,针对此问题的一个“完美”的解决方案就是动态链表。因为动态链表是不受空间限制的,而且随用随分配,非常好使。于是我建立了一个动态链表来保存我遍历到的数据,效果的确令我满意。但是,一天之后问题就来了,我又要遍历一类新的数据,也不得不采用链表这种动态存储方案。也就是说我又要把相似的代码重写一遍,而且链表的各种操作还不是闭着眼睛就能写好的。这样做无疑是非常不可取的。学习C++之前我对这个问题无可奈何,但现在我掌握了C++的模板机制,使用模板正好可以解决这个代码冗余的问题。于是我便写了一个内核下的动态存储类,方便记录各种类型的数据。下面把代码分享一下,并用一个简单地示例来演示它的使用方法。不过在这之前,要先介绍一下内核编程中的动态内存分配。

 

[……]阅读全文

30

EPROCESS劫持

昨天见群里有人提起,今天就随便写了一下。把PspCidTable中指定进程的Object改成一个自己构造的Object,从而使RING3的各种句 柄操作无效。一开始还没明白跟直接修改EPROCESS有什么区别,后来发现劫持EPROCESS更有针对性,而且比DKOM更稳定一些。很老很简单的技 术,没啥亮点。其实主要还是为了研究一下PspCidTable的稀疏数组结构,以前掌握很多理论但一直没写码遍历过这个表,今天总算是给弄明白了~之后 再看页表的结构应该也更容易理解了。代码贴上来做个记录。
 

[代码如下]
//===================头文件===================//
#include "stdafx.h"

 

//===================结构体声明===================//
typedef struct _HANDLE_TABLE_ENTRY {
    union {
        VOID* Object;
        ULONG32 ObAttributes;
        struct _HANDLE_TABLE_ENTRY_INFO* InfoTable;
 &nbs

[……]阅读全文

30

一个应用层C++写的CDriver类,用于控制驱动

昨天写好一个驱动后,准备在RING3写GUI进行交互,可是又不想自己再花时间去实现DriverLoader,于是在硬盘里找啊找~就找到了一个方便的用来控制驱动的类。
这 个class来自《Windows程序设计》(第二版)的随书代码(作者王艳平),可以方便地加载驱动、卸载驱动、发送IO控制码,原始代码有些问题我已 经将其修正,在这里贴一下,有需要的同学可以直接拿去用,#include "Driver.h"即可(把函数的实现写在头文件里貌似并不可取,不过我不想再扣出一个.cpp弄成俩文件了…)另外项目使用的字符集必须是 UNICODE

///////////////////////////////////////////////////
// Driver.h
///////////////////////////////////////////////////

#ifndef __DRIVER_H__
#define __DRIVER_H__

#include <windows.h>
#include <Winsvc.h>

class CDriver
{

public:
// 构造函数和析构函数
    // 构造函数,pszDriverPath为驱动所在目录,pszLinkName为符号连接名字
    // 在类的构造函数中,将试图创建或打开服务,
    CDriver(LPCTSTR pszDr

[……]阅读全文

30

C++中自定义结构作为函数参数的内部实现

C++自定义结构可以作为函数参数或返回值,从高级语言的角度来看这是很自然的,不过从汇编的角度想我就有点想不明白,一个复杂的 自定义结构,在作为参数进行函数调用时,参数是怎么传递的呢?以前在用C的时候就考虑过这个问题,不过一直也没深究,现在把这个问题拿出来解决一下。

自定义结构体作为函数参数
传递较为复杂的参数,比较高效的方法是使用指针,但倘若我们的代码里并没有用指针来实现,硬是把结构体作为参数类型,那么C++编译器内部是怎么做的?难道也会隐式地使用指针吗?为了进行调试,我先用C++写了一个小程序,代码如下:
 

#include <iostream>
#include <string>

 

using namespace std;

struct Student {
    char Name[10];
    unsigned short Age;
    int Score;
};

void print_stu_info(Student stu)
{
    cout << "Student Card\n"
            "Name: &

[……]阅读全文

21

[迅雷XV转换器] XVE7s简单分析

等了很久的《轩辕剑》,近期终于开播了(有同追的大牛么= =)~在网上找了找,貌似只有迅雷那里有比较高清的版本(转录的TV版720P),但下载回来发现格式是.xv而非常见的视频格式,迅雷为了“垄断片 源”,自创.xv视频格式,只能由迅雷看看播放器播放,对于我这种伪完美主义者~当然不肯轻易就范了

 

于是在网上找迅雷XV格式转换器,搜了一下发现还真有这东西,很简单的一个小程序,目前的最新版叫XVE7s,作者是“伪红学家”,地址:http://tiancaihb.ixiezi.com/2012/06/19/xve7/

 

这个版本的XVE还新加了个“一秒转换”功能,听起来很强大,下载试了下,很有效,的确是秒速把.xv转换成了.flv。当然了,速度这么快是直接对原始xv文件覆盖写入的(不然光copy一份就要好久呢)。

 

感觉这个小程序很神奇,也很简洁,习惯性拖IDA看了下,没多少sub,刨去MFC框架估计核心代码不会很多(真的很少- -!!),于是就动手分析了一下~

 

暂时只逆了1秒转换部分,支持flv,普通模式还没看。

.text:004015A8                 mov     eax, [esp+11B8h+bIsFastConv]
.text:004015AF &

[……]阅读全文

21

[DLLHijack恶意程序] LPK.DLL完整逆向

最近闲得无聊,时间都是碎片化的,毫无心情Coding

逛了逛卡饭,到病毒样本区里随便找了个小玩意Lpk.dll!看名字就知道这货是DLLHijack,体积不大没壳,正适合我这种菜鸟-_-于是下载下来仍IDA里练手

虽然没几个sub,不过还是用了我很长时间才把完整代码逆出来,因为目的是练习所以没用F5,逆完后感觉还是学到了点东西,希望下一次能有进步!!最后除了除错可以编译通过并生成mylpk.dll,不过导出表貌似没处理好,函数转发体力活懒得详细搞了生成后还得再自己添加俩资源

这个玩意貌似没啥实际作用。。释放自身到temp目录。。然后再复制自身到所有含.EXE的目录确保持久感染。。弄了个Event做线程同步,还有几个变量来回用感觉像是全局共享的于是我就pragmadata_seg(shareddata)了一下= =

.IDB+PROJECT+.DLL下载地址:http://naylon.0ginr.com/download/lpk.dll

完整逆向代码(356 Lines):

#include <stdio.h>
#include <windows.h>
#include "Shlwapi.h"

#pragma data_seg("shareddata")    
HMODULE gshModule;
HANDLE gshThread;
HANDLE gshEvent;
#pragma data_

[……]阅读全文

21

“RING3″过主防读物理内存、读写IO端口

最近拜读了王爽老师的《汇编语言》,学到了不少东西,终于能勉强逆点简单的小程序了。于是想到了Extreme神犇很早以前提出的这个点子:调用带正规签名的驱动来干坏事- –

鲁大师有正规数字签名,所以它的驱动加载时不会被主防报警,而鲁大师驱动里也没有验证调用者,所以可以利用~

以前ASM完全不懂,用IDA只会F5,一看IoDispatchControl就苦逼了,所以一直搞不定(F5的话,SystemBuffer显示成一个什么.Type,完全驴唇不对马嘴,可怕- -||)

 

于是逆了ComputerZ.sys

一开始我直接拿安装的旧版逆,结果基本接口搞得差不多了之后发现新版的360硬件大师驱动更新了= =旧的没用了。。而内部实现也有变化然后苦逼了,又下了个新的360硬件大师

果然360还是考虑得周到些,加入了SeTokenIsAdmin权限验证,调用Function时对参数的检查也严格了些,不过还是没有验证调用者XD

最后鼓捣鼓捣还是成功了

下面是我逆出的伪码(为啥说是伪码呢?因为我就是边看反汇编边翻译。。只逆了一些关键的接口,没除错,编译不能,所以只能用来看看思路,说是C代码有点对不起观众- -||   逆得很挫,大牛见笑了。。):

#include <ntddk.h>

BOOLEAN read_port_uchar(USHORT usPort, PULONG buffer)
{
    if (!is_port_legal(usPort)) {
    &n

[……]阅读全文

旧文章 «