首页
论坛
专栏
课程

[调试逆向] [原创]逆一个驱动中带Exception的函数

2010-10-14 10:22 11554

[调试逆向] [原创]逆一个驱动中带Exception的函数

2010-10-14 10:22
11554
逆一个驱动中带Exception的函数

金山推出了隐私保护器,拿来看看:
        下载地址:        http://bbs.duba.net/thread-22314119-1-1.html
1013版本。压缩包中只有一个EXE文件。不需要安装,直接运行。开始监控后,
在目录:
        C:\Documents and Settings\MyUserName\Application Data\kprivacy.exe\
下发现一个文件
        ksafefilemon.sys 文件长度 129128
这就是它的驱动了。要实现文件监控,一般还是要驱动的。

用IDA打开,分析一下这个驱动。

第一个函数 00012100 明显可以改名为 AllocMem
第二个函数 00012120 明显可以改名为 FreeMem
第三个函数 00012140 中有这么一句:

.text:0001214A                 push    offset _except_handler3

显然用到了Exception。这种带Exception代码的逆向,一般是记不住的。为了逆它,写一个测试函数:
void puts(const char* p);
void test()
{
  puts("first");
  __try
  {
    puts("seccond");
  }
  __except(0)
  {
    puts("third");
  }
}

把以上测试代码用DDK 7600.16385.0 fre x86 WXP 编译,用IDA打开生成的OBJ文件,
test函数中只出现
        call __SEH_prolog4
不行。不是我们所要的。

把以上测试代码用DDK 7600.16385.0 chk x86 WXP 编译,用IDA打开生成的OBJ文件,
test函数中出现了
        push offset __except_handler4
也不行。

为什么我们出现了 __except_handler4 而没有出现 _except_handler3 呢?网上搜索一下,
原来,新版的DDK使用了MSVC8作为编译器,就改为 __except_handler4 了。看来要找一个旧版的DDK试一试。

网上搜索,
        WIN DDK 3790.1830 ISO下载
        http://download.microsoft.com/download/9/0/f/90f019ac-8243-48d3-91cf-81fc4093ecfd/1830_usa_ddk.iso

把测试代码用DDK 3790.1830 fre x86 WXP 编译,用IDA打开生成的OBJ文件,
test函数中出现了
        call __SEH_prolog
也不行。

把测试代码用DDK 3790.1830 chk x86 WXP 编译,用IDA打开生成的OBJ文件,
test函数中出现了
        push    offset __except_handler3
终于找到了!

虽然这个 __except_handler3 比我们要找的 _except_handler3 多了一个下划线,不去深究了,我们认为它就是一样的。

还有,难道金山的这个驱动文件,是用 Checked Build 编译的?而不是一般的 Free Build ?

对比我们写的 test 函数和 sub_12140 ,就容易知道它是怎么使用 __try __except 的了。
最后,逆向出来的函数是这样的:
#include <excpt.h>

#define OUT
typedef unsigned short wchar_t;

int __stdcall sub_12140(const char* a0, OUT wchar_t* a4, unsigned short a8_len)
{
  int i = 0;  //v1c
  __try
  {
    for (i = 0; i < a8_len; i++)
    {
      a4[i] = a0[i];
    }
    return 0;
  }
  __except(EXCEPTION_EXECUTE_HANDLER) //EXCEPTION_EXECUTE_HANDLER = 1
  {
    return 0xE00B0002;
  }
}

原始的汇编是这样的:

sub_12140       proc near               ; CODE XREF: sub_1AFC0+D9p

var_20          = dword ptr -20h
var_1C          = dword ptr -1Ch
var_18          = dword ptr -18h
var_10          = dword ptr -10h
var_4           = dword ptr -4
arg_0           = dword ptr  8
arg_4           = dword ptr  0Ch
arg_8           = word ptr  10h

                push    ebp
                mov     ebp, esp
                push    -1
                push    offset dword_27C98
                push    offset _except_handler3
                mov     eax, large fs:0
                push    eax
                mov     large fs:0, esp
                add     esp, 0FFFFFFF0h
                push    ebx
                push    esi
                push    edi
                mov     [ebp+var_18], esp
                mov     [ebp+var_20], 0E00B0001h
                mov     [ebp+var_1C], 0
                mov     [ebp+var_4], 0
                mov     [ebp+var_1C], 0
                jmp     short loc_1218D
; ---------------------------------------------------------------------------

loc_12184:                              ; CODE XREF: sub_12140+6Aj
                mov     eax, [ebp+var_1C]
                add     eax, 1
                mov     [ebp+var_1C], eax

loc_1218D:                              ; CODE XREF: sub_12140+42j
                movzx   ecx, [ebp+arg_8]
                cmp     [ebp+var_1C], ecx
                jge     short loc_121AC
                mov     edx, [ebp+arg_0]
                add     edx, [ebp+var_1C]
                movsx   ax, byte ptr [edx]
                mov     ecx, [ebp+var_1C]
                mov     edx, [ebp+arg_4]
                mov     [edx+ecx*2], ax
                jmp     short loc_12184
; ---------------------------------------------------------------------------

loc_121AC:                              ; CODE XREF: sub_12140+54j
                mov     [ebp+var_4], -1
                jmp     short loc_121D5
; ---------------------------------------------------------------------------

loc_121B5:                              ; DATA XREF: .text:00027C9Co
                mov     eax, 1
                retn
; ---------------------------------------------------------------------------

loc_121BB:                              ; DATA XREF: .text:00027CA0o
                mov     esp, [ebp+var_18]
                mov     [ebp+var_20], 0E00B0002h
                mov     [ebp+var_4], -1
                jmp     short loc_121DC
; ---------------------------------------------------------------------------
                mov     [ebp+var_4], -1

loc_121D5:                              ; CODE XREF: sub_12140+73j
                mov     [ebp+var_20], 0

loc_121DC:                              ; CODE XREF: sub_12140+8Cj
                mov     eax, [ebp+var_20]
                mov     ecx, [ebp+var_10]
                mov     large fs:0, ecx
                pop     edi
                pop     esi
                pop     ebx
                mov     esp, ebp
                pop     ebp
                retn    0Ch
sub_12140       endp

dword_27C98     dd -1                   ; DATA XREF: sub_12140+5o
                dd offset loc_121B5
                dd offset loc_121BB

[公告][征集寄语] 看雪20周年年会 | 感恩有你,一路同行

最新回复 (31)
zhuliang 5 2010-10-14 10:32
2
0
好久不见了。挺想你的。
blackwhite 1 2010-10-14 18:31
3
0
卧室来看牜人的~
kuang110 6 2010-10-14 18:34
4
0
惊现大牛啊,围观中……
jerrynpc 2010-10-14 20:10
5
0
大牛出没请注意
yiyiguxing 1 2010-10-14 20:27
6
0
又学会了一招,呵呵,刘先生果然牛。。。
forgot 26 2010-10-14 20:58
7
0
F5
int __usercall sub_401000<eax>(int a1<eax>, char *a2, WORD *a3, unsigned __int16 a4)
{
  char v5; // [sp-Ch] [bp-2Ch]@1
  unsigned int v6; // [sp+0h] [bp-20h]@1
  int i; // [sp+4h] [bp-1Ch]@1
  SEHRegistrationNode __$SEHRec$; // [sp+8h] [bp-18h]@1

  __$SEHRec$.EncodedScopeTable = (int)&dword_4010B2;
  __$SEHRec$.Handler = (int)sub_4010D0;
  __$SEHRec$.Next = a1;
  __$SEHRec$.SavedESP = (int)&v5;
  v6 = 0xE00B0001u;
  __$SEHRec$.TryLevel = 0;
  for ( i = 0; i < a4; ++i )
    a3[i] = a2[i];
  return 0;
}



支持给F5写个plugin
饮水思源 2010-10-14 22:37
8
0
呵呵,大牛~
小天狼星 2010-10-14 22:39
9
0
涛哥......
evilkis 7 2010-10-14 23:26
10
0
我晕 金山也来了个隐私保护器,干脆再弄个金山浏览器 金山保险箱得了,膜拜大牛
sudami 25 2010-10-14 23:49
11
0
ks真的还山寨了一个浏览器. 只是没发布...
linhanshi 2010-10-14 23:49
12
0
Thanks for share.

Программное обеспечение выпуска и Windows Crack Обучение
Нам-Dabei Guanyin Бодхисаттва Нам без митабха
eGirlAsm 2010-10-15 10:55
13
0
Программное обеспечение выпуска и Windows Crack Обучение  
Нам-Dabei Guanyin Бодхисаттва Нам без митабха

读音

不老歌拉木闹也 哦呗呗切尼也 我不死嘎 一 windows crack 哦不切尼也
那木 大呗 观音 包的黑撒的瓦 那木 被子 米大不哈
jiangming 2010-10-15 14:04
14
0
方法不错……
学习了
LiuTaoTao 3 2010-10-15 15:13
15
0
再逆两个函数

void sub_12380(PVOID a0_pmem, ULONG a4_len, ULONG a8_align)
{
  char v9 = 0;
  if (a4_len == 0)
    return;
  ULONG p = (ULONG)a0_pmem;
  if ((a8_align - 1) & p)
  {
    ExRaiseDatatypeMisalignment();
    return;
  }
  ULONG v8 = p + a4_len - 1;
  if (p > v8 || v8 >= *MmUserProbeAddress)
  {
    ExRaiseAccessViolation();
    return;
  }
  v8 = (ULONG)PAGE_ALIGN(v8) + PAGE_SIZE; //(v8 & 0xFFFFF000) + 0x1000;
  do
  {
    v9 = *(char*)p;
    p = (ULONG)PAGE_ALIGN(p) + PAGE_SIZE;  //(p & 0xFFFFF000) + 0x1000;
  } while (p != v8);
}
bool sub_122E0(PVOID a0_pmem, ULONG a4_len)
{
  if (a0_pmem == NULL || a0_pmem >= *MmSystemRangeStart)
    return false;
  __try
  {
    sub_12380(a0_pmem, a4_len, 1);
    return true;
  }
  __except(EXCEPTION_EXECUTE_HANDLER)
  {
    return false;
  }
}
/*
可以看出函数 sub_122E0 完成的功能是,通过每个Page读一个字节,检查一段内存是否可读。

可以想象,之所以他用 checked build 而不用 free build 来编译,可能就是担心
sub_12380 中的 v9 = *(char*)p 被优化掉。 其实,可以通过把 v9 定义为 static 来解决这个问题。

这种在 __try __except 中使用
  ExRaiseStatus(NTSTATUS)
  ExRaiseAccessViolation()  STATUS_ACCESS_VIOLATION
  ExRaiseDatatypeMisalignment() STATUS_DATATYPE_MISALIGNMENT
的做法值得学习。这样,在 __except 中可以用
  GetExceptionCode()
判断出了什么事
*/
CamelLu 3 2010-10-15 16:11
16
0
噢,刘涛涛大牛,你终于出现了
cogito 2010-10-15 16:33
17
0
哇咔咔 大牛出没
jordanpz 2010-10-15 17:04
18
0
期待继续 ,,,,
throb 2010-10-15 20:06
19
0
应该不是check的,看字符串
f:\\kxengine\\defend3\\product\\release\\dbginfo\\ksafefilemon.pdb
晕菜菜 2010-10-16 00:27
20
0
支持继续~~~~~~~
pencil 5 2010-10-16 12:30
21
0
支持直接发idb
xzchina 1 2010-10-16 12:32
22
0
so.......
weolar 10 2010-10-17 18:30
23
0
呵呵……是release版的,不过我把优化关了
ImHolly 1 2010-10-17 20:02
24
0
楼上真相帝...
peowner 2010-10-17 23:37
25
0
学习大牛的方法!
herx 2 2010-10-18 10:05
26
0
这个可以学习学习
LiuTaoTao 3 2010-10-18 11:20
27
0
再逆一个函数

这个函数是计算一个unicode 字串的checksum,有两个问题:
一,数组中第8行从80到90是不是写错了,漏写了0x ?
如果真是漏写了,那这个数组也没必要了,直接 v1 = b就行了,可能是有意这么写。

二,一个特别的数组,以乘以37方式得到一个checksum,再以乘31方式得到一个checksum,
这种算法,是某种标准,还是作者随意写出来的?我还不知道

typedef unsigned char       BYTE;
typedef int                 BOOL;

BOOL __stdcall sub_12410(PCWSTR a0, OUT int* a4_checksum, OUT int* a8_checksum)
{
  static const BYTE byte_28000[256] = {
     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
    32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
    48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
    64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
    80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
    96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
    80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127, // 是不是写错了?漏写了 0x ?
   128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
   144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
   160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
   176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
   192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
   208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
   224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
   240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,
  };

  int v18 = 0, v8 = 0;
  
  if (a0 == NULL || a4_checksum == 0 || a8_checksum == 0)
    return false;

  ULONG v14 = wcslen(a0) * 2;
  for (ULONG i=0; i < v14; i++)
  {
    BYTE b = ((BYTE*)a0)[i];
    BYTE v1 = byte_28000;  // 为什么不直接 v1 = b 呢
    v18 = v18 * 37 + v1;
    v8 = v8 * 31 + v1;
  }
  *a4_checksum = v18;
  *a8_checksum = v8;
  return true;
}
sessiondiy 4 2010-10-18 11:31
28
0
英文小写转大写
zapline 2010-10-26 12:11
29
0
盟主直接放源码吧
szjohn 1 2010-10-26 13:01
30
0
围观下  大牛再次出现
dlmu 1 2010-12-7 11:11
31
0
bluecode 2010-12-7 11:42
32
0
偶是来听牛人说话地。。。
游客
登录 | 注册 方可回帖
返回