How to study C && ASM Code(2)

来源:互联网 发布:xshell mac 编辑:程序博客网 时间:2024/03/29 17:05

资料下载地址:http://www.cciss.cn/uploadFiles/lesson2.rar  (包含源代码)


                    ==www.cciss.cn.==
                             
                    How to study C && ASM Code(2)

|=---------------=[ 数据类型的问题 ]=------------------------------=|
|=-----------------------------------------------------------------=|
|=---------------=[ 7all<7all7_at_163.com> ]=----------------------=|
|=-----------------------------------------------------------------=|
|=---------------=[ 版权所有:www.cciss.cn ]=-----------------------=|

--[ Joke
  这段时间看了大量的英文资料,居然有些习惯于英文的技术资料,好几次有种冲动,
把以前写的那些文档用我蹩脚的英语再重写下:-).但仔细考虑了下,觉得冲动归冲
动,还是得先把中文学好:)这个是小组的里面我写的教学类型文档的第3篇了,前面的
两篇分别是<<逆向工程的乐趣>><<How to study C && ASM Code(1)>>,不知道有多少
朋友看过这两篇蹩脚的文章,我希望看过的有什么问题可以给我发mail:
7all7_at_163.com.在写这篇文档的时候,我试图用逆向的形式来描述C的数据类型,但
我发现好像犯了一个错误,这方面是存在规律的,但是总结比较麻烦.再因为我本身不是
计算机专业毕业,对于有些数据类型的细微的地方并不是很熟悉,如果拿我自己的想法
来描述的话,害怕出现很多的错误.故此,我把这篇文档写成了C与ASM的混杂,并尽量的
把这篇文档往题目的命名上面考虑:)

--[ 前言
  在C语言或者其它编程语言的学习过程中,数据类型一般都是前面章节必然要讲解
的问题.对于C而言,其数据类型大概的说,有char,int,long,结构等.一般情况下在
逆向完程序后,其实对于汇编而言,数据类型就有些概念模糊.虽然汇编也有字符,整型
字符串,结构等数据类型.但是在实际逆向一个程序时,特别是在动态跟踪时,我们看到
的就是操作数:)操作数有:常量/常量表达式/寄存器/内存.
  其实写到这里大家应该能够隐约感觉到,这个部分的叙述会很不清晰,但是要想省去
这个章节又感觉少了很多东西,于是还是准备硬着头皮写下去.当然在写的过程中难免
有很多的错误之处,还请大家指正:)该文档的内容还是适合于初学者,或者具备少量汇
编/C基础知识的人,对于高手可略过.
       
  提醒:希望大家在看这个文档的时候,手中有一本C或者C++的学习资料,如果有条件可以考虑
        也买本汇编的学习资料。这里我推荐大家两本比较好的资料:
        《Intel汇编语言程序设计(第四版)》
        《C Primer Plus中文版(第五版)》
        以下的代码都在Windows+VC6环境编译、调试
  备注:如果文档有不正确的地方,烦请给我发mail:7all7_at_163.com

--[ C的数据类型
  对于C而言,经常使用的就是下面列举的这个数据类型的列表.值得说明的是char类型在技术上严格
来说的话,应该属于整型,因为char用来声明字符变量/常量,而字符的打印是使用了ASCII表,所以char
类型其实存放的是16进制的ASCII码.结构和数组也是一种数据表示方式,这种方式的说明会在后面的
文档有所涉及,这里没有详细的说明.
  C的基本数据类型如下:
  int
  long
  short
  unsigned
  char
  float
  double
  signed
  bool
  //example
  int i;
  long l;
  char str;
  [...]
 
  在写该文档时,突然想到一个问题,这个问题可能会迷惑一些初学C语言的朋友,不过对于熟悉C的朋友而言,
就有些属于废话的范畴了:)
  char str[3] = "abcd";
  类似上面这样的字符数组,其数据表示形式应该是如下的形式:
  str[0] = 'a'
  str[1] = 'b'
  str[2] = 'c'
  str[3] = 'd'
 
  该文档的以下章节,会试图对C的这些数据类型与IA32 ASM的数据类型进行相关的比较,以期可以在其中发现
很多类似的地方,便于我们分析逆向后的程序:)

--[ ASM的数据表示
  ASM的内部数据类型列表:
  BYTE        8 bit unsigned integer
  SBYTE        8 bit signed integer
  WORD        16 bit unsigned integer
  SWORD        16 bit signed integer
  DWORD        32 bit unsigned integer
  SDWORD    32 bit signed integer
  [...]//other reference IA32 document
  对于逆向后的代码而言,不会象我们自己书写的ASM CODE,其数据的传输就是立即操作数(常数)/常量表达式/
寄存器/内存.这里为了说明ASM的数据表示,我们自己来书写一段IA32 ASM CODE,为的就是稍微的熟悉下ASM的一
些数据表示方式.
备注:
由于时间关系,没有自己来书写ASM CODE,源代码都来自<<Intel汇编语言程序设计>>的例子代码,
如有需要我可以提供下该例子代码的下载地址:)
A: 立即操作数的例子
  /*
     this example from <<Intel 汇编语言程序设计>>
     编译环境:Masm615
     编译选项:Make32 $YourPath/AddSub.asm
  */
  TITLE Add and Subtract              (AddSub.asm)
    ; This program adds and subtracts 32-bit integers.
    ; Last update: 2/1/02
    INCLUDE Irvine32.inc
    .code
    main PROC
        mov eax,10000h        ; EAX = 10000h //立即操作数
        add eax,40000h        ; EAX = 50000h
        sub eax,20000h        ; EAX = 30000h
        call DumpRegs //打印寄存器值的函数,该函数查看<<Intel 汇编语言程序设计>>的Irvine32.asm
        exit
    main ENDP
    END main
    ------------打印结果--------------
    C:/Masm615/exp>AddSub
  EAX=00030000  EBX=7FFDF000  ECX=00000101  EDX=FFFFFFFF
  ESI=00000008  EDI=00000001  EBP=0012FFF0  ESP=0012FFC4
  EIP=00401024  EFL=00000206  CF=0  SF=0  ZF=0  OF=0
  ----------------------------------
 
B: 对于字符的处理
  /*
    this example from <<Intel 汇编语言程序设计>>
     编译环境:Masm615
     编译选项:Make32 $YourPath/str.asm
  */
  TITLE Comparing Strings
    ; This program uses CMPSB to compare two strings
    ; of equal length.
    INCLUDE Irvine32.inc
    .data
    source BYTE "MARTIN  "
    dest   BYTE "MARTINEZ"
    str1   BYTE "Source is smaller",0dh,0ah,0 //声明字符串
    .code
    main PROC
        cld     ; direction = up
        mov  esi,OFFSET source
        mov  edi,OFFSET dest
        mov  cx,LENGTHOF source
        repe cmpsb
        jb   source_smaller
        jmp  quit
    source_smaller:
        mov  edx,OFFSET str1
        call WriteString //打印字符函数,该函数查看<<Intel 汇编语言程序设计>>的Irvine32.asm
    quit:
        exit
    main ENDP
    END main
    ------------打印结果--------------
    C:/Masm615/exp>str
    Source is smaller
  ----------------------------------
 
  从上面的内容我们可以看到,其实很多时候ASM在处理数据方面还是比较复杂的,但是却可以给人更多
编程的乐趣:)So,继续往下看,We are enter a mystery world.
--] C与ASM的混杂
  我估计很多初学者对上面的汇编代码会感觉很郁闷,如果没有学过ASM的话,这里我写了一些C与ASM混杂
的例子,并试图为下面C->ASM的数据类型做一个基本的说明.
A: 简单的C与ASM混杂的例子
源代码你可以在下载的压缩包版本内找到,项目名称为lesson21.
源代码如下:
int main(){
    int a; //声明变量
    int b;
    int c;
    int d;
    __asm{
        mov  a,eax; //把eax寄存器的值给变量a
        mov  b,ebx;
        mov  c,ecx;
        mov  d,edx;
    }
    printf("This example print some register values:)/n");
    printf("eax = 0x%x/n", a);
    printf("ebx = 0x%x/n", b);
    printf("ecx = 0x%x/n", c);
    printf("edx = 0x%x/n", d);
    return 0;
}
----------打印结果----------
This example print some register values:)
eax = 0xcccccccc
ebx = 0x7ffdf000
ecx = 0x0
edx = 0x3410b8
----------------------------
从上面的例子我们可以看到,我们通过C声明的整型变量a b c d来获取到了eax ebx ecx edx寄存器的值.
在这里额外的说明下,格式化字符串漏洞正是使用了类似上面的这样的形式来实现对漏洞程序运行流程
的控制的,当然其利用办法要复杂很多,但其基本理论与其相似,这个在后面的文档会有专门的描述:)

B: C与ASM混杂代码的提升
为了再进一步的看C与ASM混杂情况下的数据类型问题,我们把上面的程序进行了适当的修改.
源代码你可以在下载的压缩包版本内找到,项目名称为lesson21.
源代码如下:
int main(){
    int a;
    int b;
    int c;
    int d;
    __asm{
        xor  eax,eax; //eax清零,只所以使用xor也是为了后面写shellcode养成习惯而言.
        xor  ebx,ebx;
        xor  ecx,ecx;
        xor  edx,edx
        mov  eax,0x10000; //eax = 0x10000
        mov  ebx,0x20000; //ebx = 0x20000
        mov  ecx,0x30000; //ecx = 0x30000
        mov  edx,0x40000; //edx = 0x40000
        mov  a,eax;
        mov  b,ebx;
        mov  c,ecx;
        mov  d,edx;
    }
    printf("This example print some register values:)/n");
    printf("eax = 0x%x/n", a);
    printf("ebx = 0x%x/n", b);
    printf("ecx = 0x%x/n", c);
    printf("edx = 0x%x/n", d);
    return 0;
}
----------打印结果----------
This example print some register values:)
eax = 0x10000
ebx = 0x20000
ecx = 0x30000
edx = 0x40000
----------------------------
在上面的例子中,我们把寄存器赋值常数(立即操作数),然后再给变量a等:)通过上面的例子我想大家应该
对立即操作数的操作有些稍微的熟悉了,但这些还远远不够:)

C: C与ASM混杂对字符串的处理
int main(){
    const char *str;
    __asm
    {
        pushad;
        mov eax,0x64636261;
        mov dword ptr [str],eax;
        popad;
    }
    printf("This example for strings:)/n");
    printf("str = %s/n", &str);
    return 0;
}

在这个例子中,我们声明了一个字符串指针,然后通过把0x64636261(即abcd,后进先出)赋值给eax,进而
把该值赋给变量str来使str获取ASM操作中的内存数值并打印:)
----------打印结果----------
This example for strings:)
str = abcd
----------------------------

D: C与ASM混杂对字符串的处理的另外的方式
Under this console application code,i think it's fun:)
源代码如下:
int main(){
    const char *str = "abcd";
    const char *dest;
    __asm{
        pushad;
        xor eax,eax;
        mov eax,dword ptr [str];
        mov dword ptr [dest],eax;
        popad;
    }
    printf("This example for strings:)/n");
    printf("dest = %s/n", dest);
    return 0;
}
这个例子是为了对字符串的赋值做一个另外方式的说明,在很多逆向后的代码中都有很多类似这种方式的
赋值,当然如果逆向的程序比较大,其赋值过程也会比较复杂.
----------打印结果----------
This example for strings:)
dest = abcd
----------------------------

--] 逆向后数据类型如何理解?
  对于逆向后我们看到的ASM CODE的数据类型,我们可以简单理解为立即操作数/常量表达式/内存值,至于
其详细的数据类型可以暂时的放一放,等待对ASM精通后再进行更进一步的学习,如果有什么问题可以mail
联系.
  下面我写了一个简单的C程序,并从ASM的角度来叙述下:)
  源代码如下:
  int main(){
        int  i = 8;
        char *str = "abcdefghijklm";
        long int j = 9999999999;
        printf("i = %d/nstr = %s/nj = %d/n", i, str, j);
        exit(0);
    }
    为了简单我们仅把变量赋值的ASM CODE写出来:
    4:        int  i = 8;
    00401028   mov         dword ptr [ebp-4],8 //把8存放到ebp-4,这里也是变量i的初始化内存地址
    5:        char *str = "abcdefghijklm";
    //把变量str的字符串值存放到ebp-8
    0040102F   mov         dword ptr [ebp-8],offset string "abcdefghijklm"
    6:        long int j = 9999999999;
    00401036   mov         dword ptr [ebp-0Ch],540BE3FFh //同上
   
    Yuk,通过对上面这个简单程序的逆向,我们发现了一个有趣的事情,我们试图整篇讲解的数据类型,在
逆向的情况下,仅仅是如上的一些内存赋值过程:)但是,前面我写的一些简单的C与ASM混杂的例子还是
有用处的.
 
----[ 总结   
  又到了写总结的时候了,这篇文档是迄今为止令人最厌烦的一篇,虽然我一直试图写的清晰些,但还是不
能清晰,所以也只有这样草草结尾:)

 
原创粉丝点击