吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 9772|回复: 16
收起左侧

[其他原创] 2、数据的存储空间 ------ 变量

  [复制链接]
datochan 发表于 2009-3-31 01:22
本帖最后由 bester 于 2009-3-31 01:32 编辑

2、数据的存储空间 ------ 变量
         估计大家都知道,我们程序访问的数据一般的都是存放在内存或者寄存器中。自然的,如上次课所讲的那些数据也都是存放在内存中的,那我们在程序中,如何使用这些内存空间呢?这就有了“变量”的概念。
          我们在这里引用一下上一篇文字的图片:
         

这个图片不陌生吧~~~~
这里的00438400就是一个变量~,如果以一个字节的方式来读的话,它是一个BYTE类型的变量,它的内容是0xA100438401的内容就是0xA5,如果以WORD类型来读的话,00438400的内容是0xA5A1,如果以DWORD类型来读的话,00438400的内容是0x0000A5A1,想必经过上次的学习,我们已经能够理解这些小概念了!
那变量的含义也就很清楚了,变量就是内存地址。学过编程的可能觉得不理解,编程高手可能就笑我不求甚解了,所以,如果我有什么理解不对的,不深刻的,还请各位大牛指教!


稍微熟悉点程序的人,应该知道,我们的程序被分成了代码段,数据段,资源段,堆栈段等等……

上面我们说到过 变量就是地址,那反过来说,地址就是变量,似乎也是成立的!

比如: 我们的程序代码是写在内存里的,也就是说,我们的代码也可以当作变量来使用!

想想我们写程序,不就是用代码通过变量来操作数据吗?我们写的程序本身就是在内存里放着的,代码的每个字节都有一个虚拟地址与它对应,也就是说,我们的代码本身就是一些数据。

从这里来看,似乎高手们讲的什么钩子,代码自变形,甚至我们的代码是可以放在数据区执行的等等技术,似乎也不是什么谣不可及的……



想必,大家对普通的变量应该有一定的认识了,这里呢,我就给出变量在C语言中的声明和表示方法!



C语言中,我们的变量声明格式是:
数据类型
变量名;
或者
数据类型
变量名 = 常量;

C语言中,常见的数据类型有 intfloat/doublechar

整型中又分成了,longshort等,多了我不介绍,大家自己百度一下吧~

上文中的常量就是一个具体的数值!

              例如:  int   x = 2;             //     我们定义了一个变量x它的内容是2


如果我们要定义一个连续的字符串,
比如:
char
addrName[] = “52pojie.cn\0”;

这样我们就定义了一个数组,addrName[0]中的内容就是‘5addrName[1]中的内容就是‘2addrName[6]中的内容就是’e’了,依次类推!

这个字符串它在内存中的样子大概如下:
   

也就是说,我们的addrName[0]就是内存中的地址0x00438AC0addrName[1]就是内存中的地址0x00438AC1
这里需要说明的一点,就是,所有的变量名,函数名,对象名等等,都是它所代表的内存地址的首地址!也就是说:
addrName == addrName[0] == 0x00438AC0

好了,由于我还没有能力写基础教程,所以,这里对C变量相关的基础就说到这里,再次回到我们的主题:变量就是地址!

如果我们有一个需求,就是将我们上面声明的这个字符串变量输出出来,那我们的程序需要怎么写呢?
// test.cpp : Defines the entry point for the application.
//
#include "stdio.h"
#include <windows.h>
char
addrName[] = "52pojie.cn\0";
char

*szTitle

= "Null\0";
// Foward declarations of functions included in this code module:
int main()
{

MessageBoxA(NULL, addrName , szTitle, MB_OK);

return 0;
}

像我们搞破解的,一定不会对这个MessageBoxA函数陌生吧~~,它反汇编的样子大概是:
                  
               相关内存的帖图:
                  

            
大家自己根据我提供的截图,算一下上面push后面的地址的内容想必就应该很清楚的发现,我们在程序中使用的变量就是直接使用的地址,比如:
00401008
|.
68 30604000
push
00406030
; |Text = "52pojie.cn"
这里的00406030 就是字符串52pojie.cn的首个地址,那EAX中的是什么内容啊?应该也是地址吧~~~

我们看一下0x0040603C中的内容,也就是EAX的内容:0x00406040,再看一下0x00406040中的内容,很容易的发现,原来是“Null”,奇特吧~~~

这个就是我们C语言中说到的指针的概念,很多没有好好学C语言的朋友可能都迷糊指针的概念,我们通过这个例子就应该可以很容易的明白,指针就是变量的地址或者直接说指针就是地址的地址!

指针在C语言中的表示就是*,在汇编语言中的表示就是[],至于为什么要有指针,指针到底有什么作用,在写程序的过程中,指针的功能到底应该怎么使用,我会在以后的指针的课题中详细介绍!

这次的内容基本就到这里了,为了开阔大家的视野,不局限与传统的思路里,我给出一个把函数当作数组使用的一个例子:打印99乘法表,虽然没有什么技术含量,但是希望能给大家一个提示,起到开阔视野的作用!

#include       "stdio.h"
#include      
"windows.h"
typedef          unsigned
char       BYTE;

typedef VOID (CALLBACK
*MYSPRINTF)(char
*, const
char
*,);
typedef VOID (CALLBACK
*MYLSTRCAT)(char
*, char
*);
typedef VOID (CALLBACK
*MYMSGBOX)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);

MYSPRINTF mySprintf
= (MYSPRINTF)GetProcAddress(LoadLibraryA("msvcr71.dll"), "sprintf");
MYLSTRCAT myStrCat
= (MYLSTRCAT)GetProcAddress(LoadLibraryA("KERNEL32.dll"), "lstrcatA");
MYMSGBOX  myMsgBox
= (MYMSGBOX)GetProcAddress(LoadLibraryA("user32.dll"), "MessageBoxA");


BYTE    buf[]        
= {   

0xB8,0x00,0x12,0x00,0x00,0xE8,0xAE,0x00,0x00,0x00,0x55,0x56,0x57,0xB9,0x7F,0x00,\
0x00,0x00,0x33,0xC0,0x8D,0x7C,0x24,0x0D,0xC6,0x44,0x24,0x0C,0x00,0xC6,0x84,0x24,\
0x0C,0x02,0x00,0x00,0x00,0xF3,0xAB,0x66,0xAB,0xAA,0xB9,0xFF,0x03,0x00,0x00,0x33,\
0xC0,0x8D,0xBC,0x24,0x0D,0x02,0x00,0x00,0xBE,0x01,0x00,0x00,0x00,0xF3,0xAB,0x66,\
0xAB,0xAA,0xBF,0x01,0x00,0x00,0x00,0x3B,0xF7,0x7C,0x33,0x8B,0xEE,0xA1,0x18,0x61,\
0x40,0x00,0x55,0x57,0x56,0x8D,0x4C,0x24,0x18,0x50,0x51,0xFF,0x15,0x20,0x86,0x40,\
0x00,0x83,0xC4,0x14,0x8D,0x54,0x24,0x0C,0x8D,0x84,0x24,0x0C,0x02,0x00,0x00,0x52,\
0x50,0xFF,0x15,0x28,0x86,0x40,0x00,0x47,0x03,0xEE,0x3B,0xFE,0x7E,0xCF,0x8D,0x8C,\
0x24,0x0C,0x02,0x00,0x00,0x68,0x24,0x61,0x40,0x00,0x51,0xFF,0x15,0x28,0x86,0x40,\
0x00,0x46,0x83,0xFE,0x0A,0x7C,0xAB,0x6A,0x00,0x8D,0x94,0x24,0x10,0x02,0x00,0x00,\
0x68,0x28,0x61,0x40,0x00,0x52,0x6A,0x00,0xFF,0x15,0x24,0x86,0x40,0x00,0x5F,0x5E,\
0x5D,0x81,0xC4,0x00,0x12,0x00,0x00,0xC3\
};

BYTE AllocBuf[]        
= {    0x51,0x3D,0x00,0x10,0x00,0x00,0x8D,0x4C,0x24,0x08,\
0x72,0x14,0x81,0xE9,0x00,0x10,0x00,0x00,0x2D,0x00,\
0x10,0x00,0x00,0x85,0x01,0x3D,0x00,0x10,0x00,0x00,\
0x73,0xEC,0x2B,0xC8,0x8B,0xC4,0x85,0x01,0x8B,0xE1,\
0x8B,0x08,0x8B,0x40,0x04,0x50,0xC3\
};
const
char
*pConChar        =
"%d*%d=%-4d\0";
const
char
*pTitle        =
"九九乘法表\0";
char
*pNchar        =
"\n";

void main()
{
   
long*    pVoid = (long
*)buf;
    __asm
    {
        CALL pVoid;
    }
}





         帖一下效果图吧:

ShowTable.rar

11.29 KB, 下载次数: 16, 下载积分: 吾爱币 -1 CB

免费评分

参与人数 1威望 +2 收起 理由
zapline + 2 感谢发布原创作品,[吾爱破解]因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

zzage 发表于 2009-4-1 10:34
[s:20]~~坐在沙发上学习!!!!!
onlylovewww 发表于 2009-4-1 11:59
学习下

BYTE    buf[]        = {   

0xB8,0x00,0x12,0x00,0x00,0xE8,0xAE,0x00,0x00,0x00,0x55,0x56,0x57,0xB9,0x7F,0x00,\
0x00,0x00,0x33,0xC0,0x8D,0x7C,0x24,0x0D,0xC6,0x44,0x24,0x0C,0x00,0xC6,0x84,0x24,\
0x0C,0x02,0x00,0x00,0x00,0xF3,0xAB,0x66,0xAB,0xAA,0xB9,0xFF,0x03,0x00,0x00,0x33,\
0xC0,0x8D,0xBC,0x24,0x0D,0x02,0x00,0x00,0xBE,0x01,0x00,0x00,0x00,0xF3,0xAB,0x66,\
0xAB,0xAA,0xBF,0x01,0x00,0x00,0x00,0x3B,0xF7,0x7C,0x33,0x8B,0xEE,0xA1,0x18,0x61,\
0x40,0x00,0x55,0x57,0x56,0x8D,0x4C,0x24,0x18,0x50,0x51,0xFF,0x15,0x20,0x86,0x40,\
0x00,0x83,0xC4,0x14,0x8D,0x54,0x24,0x0C,0x8D,0x84,0x24,0x0C,0x02,0x00,0x00,0x52,\
0x50,0xFF,0x15,0x28,0x86,0x40,0x00,0x47,0x03,0xEE,0x3B,0xFE,0x7E,0xCF,0x8D,0x8C,\
0x24,0x0C,0x02,0x00,0x00,0x68,0x24,0x61,0x40,0x00,0x51,0xFF,0x15,0x28,0x86,0x40,\
0x00,0x46,0x83,0xFE,0x0A,0x7C,0xAB,0x6A,0x00,0x8D,0x94,0x24,0x10,0x02,0x00,0x00,\
0x68,0x28,0x61,0x40,0x00,0x52,0x6A,0x00,0xFF,0x15,0x24,0x86,0x40,0x00,0x5F,0x5E,\
0x5D,0x81,0xC4,0x00,0x12,0x00,0x00,0xC3\

里面的0xXX是怎么来的?能解释下  我菜鸟
zapline 发表于 2009-4-1 12:27
本帖最后由 zapline 于 2009-4-1 12:44 编辑

VISTA+VC6
为什么debug模式编译会出错
release模式编译就不会呢?
zapline 发表于 2009-4-1 13:18
本帖最后由 zapline 于 2009-4-1 13:20 编辑

把函数当数组
看了一下
似乎有点shellcode的感觉
; int __cdecl main(int argc, const char **argv, const char *envp)
_main proc near

pVoid= dword ptr -4
argc= dword ptr  8
argv= dword ptr  0Ch
envp= dword ptr  10h

push    ebp
mov     ebp, esp
push    ecx
mov     [ebp+pVoid], offset buf
call    [ebp+pVoid]
mov     esp, ebp
pop     ebp
retn
_main endp
.data:00406030 buf:                                    ; DATA XREF: _main+4o
.data:00406030                 mov     eax, 1200h
.data:00406035                 call    AllocBuf
.data:0040603A                 push    ebp
.data:0040603B                 push    esi
.data:0040603C                 push    edi
.data:0040603D                 mov     ecx, 7Fh
.data:00406042                 xor     eax, eax
.data:00406044                 lea     edi, [esp+0Dh]
.data:00406048                 mov     byte ptr [esp+0Ch], 0
.data:0040604D                 mov     byte ptr [esp+20Ch], 0
.data:00406055                 rep stosd
.data:00406057                 stosw
.data:00406059                 stosb
.data:0040605A                 mov     ecx, 3FFh
.data:0040605F                 xor     eax, eax
.data:00406061                 lea     edi, [esp+20Dh]
.data:00406068                 mov     esi, 1
.data:0040606D                 rep stosd
.data:0040606F                 stosw
.data:00406071                 stosb
.data:00406072
.data:00406072 for1:                                   ; CODE XREF: .data:004060C5j
.data:00406072                 mov     edi, 1
.data:00406077                 cmp     esi, edi
.data:00406079                 jl      short over
.data:0040607B                 mov     ebp, esi
.data:0040607D
.data:0040607D for2:                                   ; CODE XREF: .data:004060ACj
.data:0040607D                 mov     eax, off_406118 ; "%d*%d=%-4d"
.data:00406082                 push    ebp
.data:00406083                 push    edi
.data:00406084                 push    esi
.data:00406085                 lea     ecx, [esp+18h]
.data:00406089                 push    eax
.data:0040608A                 push    ecx
.data:0040608B                 call    sprintf
.data:00406091                 add     esp, 14h
.data:00406094                 lea     edx, [esp+0Ch]
.data:00406098                 lea     eax, [esp+20Ch]
.data:0040609F                 push    edx
.data:004060A0                 push    eax
.data:004060A1                 call    lstrcatA
.data:004060A7                 inc     edi
.data:004060A8                 add     ebp, esi
.data:004060AA                 cmp     edi, esi
.data:004060AC                 jle     short for2      ; "%d*%d=%-4d"
.data:004060AE
.data:004060AE over:                                   ; CODE XREF: .data:00406079j
.data:004060AE                 lea     ecx, [esp+20Ch]
.data:004060B5                 push    offset unk_406124 ; "\n"
.data:004060BA                 push    ecx
.data:004060BB                 call    lstrcatA
.data:004060C1                 inc     esi
.data:004060C2                 cmp     esi, 10         ; 1->9
.data:004060C5                 jl      short for1
.data:004060C7                 push    0
.data:004060C9                 lea     edx, [esp+210h]
.data:004060D0                 push    offset aIA      ; "九九乘法表"
.data:004060D5                 push    edx
.data:004060D6                 push    0
.data:004060D8                 call    MessageBox
.data:004060DE                 pop     edi
.data:004060DF                 pop     esi
.data:004060E0                 pop     ebp
.data:004060E1                 add     esp, 1200h
.data:004060E7                 retn
问一下
.data:0040603D                 mov     ecx, 7Fh
.data:00406042                 xor     eax, eax
.data:00406044                 lea     edi, [esp+0Dh]
.data:00406048                 mov     byte ptr [esp+0Ch], 0
.data:0040604D                 mov     byte ptr [esp+20Ch], 0
.data:00406055                 rep stosd
.data:00406057                 stosw
.data:00406059                 stosb
.data:0040605A                 mov     ecx, 3FFh
.data:0040605F                 xor     eax, eax
.data:00406061                 lea     edi, [esp+20Dh]
.data:00406068                 mov     esi, 1
.data:0040606D                 rep stosd
这一段是什么意思?
 楼主| datochan 发表于 2009-4-1 16:16
我按照顺序回答一下吧,如果不明白就提出来,我再讲:
里面的0xXX是怎么来的?能解释下  我菜鸟


由于最近时间比较紧,写的比较仓促,这个文章中,我举了数组变量的例子,再OD的 数据区查看过它的 面目了!

最后给的这个例子中,其实是将99乘法表作为数组的形式再OD的数据区查看,大家就会看到函数的数组形式的机器码,模样跟数据一模一样,完全可以当做数组使用!

至于这些0xXX的 数字就是程序代码的二进制机器码!,来源于OD的数据区
 楼主| datochan 发表于 2009-4-1 19:22
VISTA+VC6
为什么debug模式编译会出错
release模式编译就不会呢?
zapline 发表于 2009-4-1 12:27


这个比较好回答!
原因有两个:
                   1、debug模式下编译的程序,编译器不对程序进行优化处理,而且还再程序里面加了好多类似断言之类的信息
                   2、我给出的所有的机器码都是再release下编译的,所以,你再debug模式下机器码就变了,两个数组之间相互调用的编译也变了,所以导致的崩溃
最后,
如果你有兴趣,可以把这个程序改成debug模式下可运行的……
 楼主| datochan 发表于 2009-4-2 14:33
把函数当数组
看了一下
似乎有点shellcode的感觉; int __cdecl main(int argc, const char **argv, const char *envp)
_main proc near

pVoid= dword ptr -4
argc= dword ptr  8
argv= dword ptr  0Ch
envp ...
zapline 发表于 2009-4-1 13:18


刚发现,原来还有一个问题!

这个估计不是我的能力范围了,需要自己看汇编语言了!
另外,我简单的说一下吧,我申请了一个数组空间,需要给它初始化呀~~
晓外 发表于 2009-4-10 17:04
又学习了,,收藏~~~
明次 发表于 2009-4-10 19:21
有点难度 看不懂
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 22:40

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表