资料下载地址: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混杂的例子还是
有用处的.
----[ 总结
又到了写总结的时候了,这篇文档是迄今为止令人最厌烦的一篇,虽然我一直试图写的清晰些,但还是不
能清晰,所以也只有这样草草结尾:)
How to study C && ASM Code(2)
最新推荐文章于 2021-08-16 21:06:35 发布