longblock sizee=0,为什么要写这个出来?和下面的哪个东西有关系?

豆丁微信公众号
君,已阅读到文档的结尾了呢~~
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
房价问题事数学建模优秀论文
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='http://www.docin.com/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口C/C++ long a[2]={0}; 那sizeof(a)为多少?及为什么?_百度知道
C/C++ long a[2]={0}; 那sizeof(a)为多少?及为什么?
答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
16long 的长度为 64 bit,即 8 个字节,数组长度为 2,因此是 16。我的是 64 位系统…
采纳率:28%
这样明白了吧,还有具体的大小还要看具体的环境系统,我的是32位系统,一个long占4个字节(64位系统好像是一个long就占8个字节了吧),你数组a有两个空间,所以就是8罗
sizeof(a)是整个数组的大小,还是数组第一个元素的大小?一般不是int是4个字节,long是8个字节码?
整个数组的大小,这个要看系统罗,你看我的系统的long就是4个字节.......你可以这样来看各种数据类型的大小,cout && sizeof(long) && 这样输出的就是你计算机里面,一个long型数据的大小,可以换成int,double等等其他的去查看它的大小;还有一种情况就是,你给指针分配连续内存当做数组的话,example:long * a =
a = new long [2] ();
cout && sizeof(a) &&如果这样的话,不论你整个数组多大,是哪种数据类型,它的大小都是一样的,都是一个指针类型的大小,至于指针类型的大小是多大,这个又要看系统环境啦,我的指针类型大小就是 4个字节
为您推荐:
其他类似问题
sizeof的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。学会等待。。。
c语言之不再害怕sizeof(struct)
程序员在面试的时候经常会碰到一些题目,给出一个结构体,然后sizeof它一下,问值是多少?比如给出下面这样一个结构体:
struct test{
也许一些刚开始学习c语言的同学就会毫不犹豫的把struct当中每个变量所占用的空间相加,等到的结果是8。之后结果就错了。为什么呢,首先让把他们的地址打印出来看个究竟,这是打印出来的结果:a=0x,b=0x0000002,c=0x,d=0x. 很奇怪吧,不像我们预想的那样,他们是按顺序存储的。这就涉及到一个内存排列的问题:内存对齐。
首先解释一下,为什么要内存对齐呢,这和我们的处理器的特性有关系,总线读取内存总是从偶数字节开始的,如果按照顺序进行排列的话,short b 排列的内存地址应该是:0x,但是它需要占用两个字节的内存空间,如果它要在这个内存地址开始存放的话,需要被读取两次,而且读取完成之后还要进行内存内容拼接,才能完整的得到这个short型的变量。如果它在b=0x0000002这个地址开始存放,那么只需要读取一次而且不需要进行内存内容的拼接。然后变量c开始从b之后存放,地址是0x,但是它只占了一个字节,同样的道理,剩余的空间不能用来存放,但是既然处理器是从偶数字节开始读取的,那么为什么d的开始地址是0x呢。别着急,还有一个规定,就是一个字也就是16bits,双字(32bits)操作数如果跨越了4字节边界,或者一个四字操作数跨越了8字节边界被认为是未对齐的。也就是说,如果d从0x开始存放的话,那他就要跨越0x这个能整除4的边界,故而需要两次的内存读写。可以回头看看short
b,它是从0x开始存放的,但是它并没有跨越0x这个边界值。
还可以举出这样一个例子:
#include&iostream&
struct test{
int main() {
int x1 = (unsigned int)(void*)&t.a - (unsigned int)(void*)&t;
int x2 = (unsigned int)(void*)&t.b - (unsigned int)(void*)&t;
int x3 = (unsigned int)(void*)&t.c - (unsigned int)(void*)&t;
int x4 = (unsigned int)(void*)&t.d - (unsigned int)(void*)&t;
int x5 = (unsigned int)(void*)&t.e - (unsigned int)(void*)&t;
printf("a=0x%p,b=0x%p,c=0x%p,d=0x%p,e=0x%p", x1, x2, x3, x4, x5);
cin.get();
}可以看看打印出来的结果, d的其实地址是0x, 因为如果它从0x开始存放的话,那就它跨越了边界。
还有一个比较特殊的情况,那就是char类型的变量比较随和,因为他在32位的处理器中就占有一个字节,因此把它放在哪里它都不介意,也就是说,因为它只占一个字节,无论存放在哪里,都只需要读取一次。
看这样一个例子:
struct test{
打印出来的结果是:a=0x,b=0x0000002,c=0x,d=0x.
缺省的情况下,编译器默认把结构,栈中的成员数据进行内存对齐。这样以浪费内存空间的方式节省总线运作的代价。
接下来说一下 #pragma pack(n)这个预处理,主要的功能是改变内存对齐方式的选项,按照给定的n字节进行内存对齐。但是结构体成员对齐的方式有一个很重要的特点,就是最小原则。结构体成员对齐的规则如下: 将自己的本身在内存中实际占用的字节和当前由#pragma pack(n)设定的n进行比较,取其中最下的那个作为结构体当前成员的对齐方式,但是不影响其他结构体成员的对齐方式。
举个例子:
#pragma pack(8)
struct test_st1{
struct test_st2{
struct test_st1 st1;
上面这个例子设定的内存对齐方式是8字节对齐形式。那么我们看看结构体test_st1,其中a所占内存大小为1,和规定的比较,取最小的,故对齐方式为1字节对齐,对于成员b,因为它占用4个字节,而规定的是8,所以取最小的,对齐方式为4字节对齐,就是从内存地址可以整除4紧挨a存放的地址开始存放b,可以得到结构体的大小为8字节。
之后再来看看结构体test_st2这个结构体,c是本身是一个字节,所以对齐方式是1,而st1是一个结构,那么这个结构本身在其他结构体中,对齐的方式是什么呢,是以结构体的大小和给定的对齐方式做比较吗?不对,它的对齐方式是它成员变量中最大的那个成员变量所占的内存空间和给定的值进行比较,继而,st1的对齐方式是4,它的起始地址是可以整除4的地方开始。 对于d,因为它占用8个字节的内存,所以它的对齐方式是8,c和st1用去了12个字节,所以d从内存地址可以整除8的地方开始存放,所以这个test_st2结构体的大小是24.给出一个完整的测试程序:
#include&iostream&
#pragma pack(8)
struct test_st1{
struct test_st2{
struct test_st1 st1;
int main() {
struct test_st2
int x1 = (unsigned int)(void*)&t.c - (unsigned int)(void*)&t;
int x2 = (unsigned int)(void*)&t.st1.a - (unsigned int)(void*)&t;
int x3 = (unsigned int)(void*)&t.st1.b - (unsigned int)(void*)&t;
int x4 = (unsigned int)(void*)&t.d - (unsigned int)(void*)&t;
printf("a=0x%p,b=0x%p,c=0x%p,d=0x%p", x1, x2, x3, x4);
cin.get();
可以自行调试一下,看看内存中他的内存排列。
sizeof(struct)的结果分析及其原因
实例讲解c语言结构体大小 sizeof(struct A)
sizeof理解03---sizeof(struct)
sizeof(struct )大小讨论
C当中关于sizeof(struct)和sizeof(union)
C语言 sizeof(struct)讲解
C语言中的sizeof(struct )和sizeof(union)
结构体(struct) 的 sizeof 大小
C语言sizeof的计算方式
Struct对sizeof的详解
没有更多推荐了,利用pe添加节的方法添加代码 实现简单的加壳大致流程如下要达到的目的是 添加一个新节 在新节中添加自己的代码 让程序运行时 先运行自己的代码而自己的代码就是为了解开之前对程序进行的加密执行完后 再继续运行原程序的路线。详细步骤第一步先写程序将 采用文件映射的方法将待修改的exe加载进来 获取所有我们需要的信息CreateFile
CreateFileMapping
MapViewOfFile(返回 文件基地址 Pimage)GetFileSize(用于修改文件大小)第二步初始化pe头信息 DOS=PIMAGE_DOS_HEADER(Pimage); 其他初始化略验证pe的有效性 MZ 和 PE第三步开始加节 因为后边要修改eop所在的节的内容所以先将此节的属性设置为 可读可写
IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE(此处很关键 自己修改的事飞秋 结果修改完后一直不能运行 卡了很长时间 切记)加节1找到最后一节的地址PIMAGE_SECTION_HEADER lastsec = SECTION+(FILE-&NumberOfSections-1);
确定新加节的地址PIMAGE_SECTION_HEADER newsec = lastsec+1;
节表数目加1 FILE-&NumberOfSections++;验证一下 在节表头最后 到 第一个节内容开始 有没有40个字节(一般都有
没有考虑不够的情况)验证方法(主要明白SizeOfHeaders的真实含义)NEWSIZE 计算的是 (dos + dos stub ) + nt +
新加节后的节表头总大小(纯粹大小 未对齐)DWORD NEWSIZE = (DOS-&e_lfanew)+sizeof(IMAGE_OPTIONAL_HEADER32)+sizeof(IMAGE_SECTION_HEADER)*NumberOfS(不要忘记 dos stub
直接用(sizeof(IMAGE_DOS_HEADER))尽管没有神马影响 但是事实 必须这样计算)让它跟原SizeOfHeaders比较SizeOfHeaders是
dos+dos stub+nt+所有节表头总大小(对齐后的)
可以用作第一个节内容的开始位置2大小满足之后
对新加节的所有属性进行初始化(UP函数是 用来对齐的 参数 1 大小 2 对齐粒度)memcpy(newsec-&Name,".NewSec",8);newsec-&Misc.VirtualSize=实际大小(size); 节内容的实际大小
SizeOfRawData 用到newsec-&SizeOfRawData=Up(size,pe.OPTION-&FileAlignment); 文件中的大小newsec-&VirtualAddress 在内存中的RVA 重要 可以利用上一个节的数据得到DWORD last =Up((lastsec-&SizeOfRawData),pe.OPTION-&SectionAlignment)+lastsec-&VirtualADWORD last =Up((LastSec-&Misc.VirtualSize),pe.OPTION-&SectionAlignment)+lastsec-&VirtualA两个last 相等 因为 SizeOfRawData 是Misc.VirtualSize按文件对齐得到的文件对齐粒度512 内存对齐粒度4096 所以肯定相等不过为了准确 采用后者其实这个last 也就是 pe文件 载入内存后 经过SectionAlignment对齐后 的 总大小 SizeOfImagenewsec-&PointerToRawData=lastsec-&PointerToRawData+lastsec-&SizeOfRawD
同理newsec-&Characteristics=IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; 可读可写其他属性没有什么影响 故均设置为0
到此 初始化完毕3需要修改的其他地方的参数a (必须)文件在磁盘上的总大小 即第一步中的GetFileSize返回的值 再加上一页的大小4096
用于CreateFileMapping创建文件映射对象函数 把大小设置为修改后的大小 即 加上4096后的值b (必须)文件映射内存后的总大小
OPTION-&SizeOfImage+=Up(size,pe.OPTION-&SectionAlignment);c (不必须的)
pe.DATA[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size=0;
pe.DATA[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress=0;
pe.OPTION-&SizeOfCode+=Up(size,pe.OPTION-&SectionAlignment);
pe.OPTION-&SizeOfInitializedData+=Up(size,pe.OPTION-&SectionAlignment);4 至此加节成功第四步取反因为是对 eop所在节的内容取反 所以要找到 eop 所在节方法 获取eop= OPTION-&AddressOfEntryPoint 然后循环遍历各个节表头的起始地址 进行比较for (int i=0; i&FILE-&NumberOfS i++){PIMAGE_SECTION_HEADER sec = PIMAGE_SECTION_HEADER(SECTION+i);if (eop&=sec-&VirtualAddress
eop&=(sec-&VirtualAddress+sec-&SizeOfRawData)){}}找到所在节后
是要对在磁盘上此节的内容 进行修改 所以获取PVOID address = sec-&PointerToRawData+ //文件的地址DWORD lenth
= sec-&SizeOfRawD
//文件的大小取反函数void
_stdcall QF(PVOID address,DWORD len){DWORD i=0;PBYTE buf=(PBYTE)for ( i=0; i& i++){buf[i]=~buf[i];} } 函数中有一个关键字 _stdcall
作用是 函数执行完后 自己跳转到之前压栈的地址 用于返回eop使用好了 取反结束了 此时 磁盘上的 exe文件已经被 破坏 接下来是 解密第五步解密 比较复杂首先说一下思路解密其实是 exe在执行后 先执行自己的解密算法 在跳转回去 继续自己的程序所以解密 就是当exe文件执行时 先执行自己的代码 即将已取反加密的节再取反 即可正常运行记住是当exe文件执行的时候所以 需要获得当 exe文件加载进去后的 内存地址才行(重要)并不是说将磁盘上的文件再改回来 这样想是错的 再怎么说文件执行了 再对它进行修改 肯定是不行的获得了待解密的节首地址 和 大小 此时解密函数参数已经解决了 接下来要做的 是让程序运行的时候 先执行自己的代码也就是先执行自己的这个解密算法函数
一个函数运行的步骤是 先将参数从右到左依次入栈 再将代码入栈 而我们还需要执行完后 再跳转回原eop入口地址 所以再将原eop入口地址入栈 待函数执行完后 返回到这个地址 怎么返回的? 这就用到关键字 _stdcall
它的作用是
由被调的函数清除堆栈 它的反汇编是 ret 8 ;两个字节的大小(在这个程序中不用它也可以 用是最安全 省心的 至于原因 强哥解释了 我没太搞明白)接下来就开始copy应该copy的内容到新加节的内容中参数入栈 需要自己写机器语言(因为是执行自己的函数所以自己调) 利用结构体 形成语句 然后再copy到新加节的开始当执行新加节的内容时 先执行自己做的这个解密函数(参数入栈
原eop入栈 代码入栈 ret 8)1 获得copy的首地址 即 新加节的文件地址
PBYTE begin=(RVATORAW(newsec-&VirtualAddress)+image); 再将 参数入栈的机器码构成结构体 直接copy机器码到新加节中2 从右到左 copy参数 即先copy 节的长度length先对之前自己做的结构体进行初始化MOV_EBX.address=secofeop-&SizeOfRawD
//所在节的lengthMOV_EAX.address=secofeop-&VirtualAddress+pe.OPTION-&ImageB //所在节的起始地址 va+400000PUSH_OLD_EOP.address=pe.OPTION-&AddressOfEntryPoint+pe.OPTION-&ImageB //原eop+400000再copy到新加节的内容中memcpy(begin,&MOV_EBX,sizeof(mov_eax));
//所在节的lengthmemcpy(begin+sizeof(mov_eax),&MOV_EAX,sizeof(mov_eax)); //所在节的起始地址 va+400000memcpy(begin+sizeof(mov_eax)*2,&PUSH_OLD_EOP,sizeof(push_old_eop)); //原eop+400000DWORD lenofcode=(DWORD)end_qf-(DWORD)start_//其中 start_qf
end_qf 是取反函数的首地址和末地址 用来计算代码的长度 注意最后还得加上末地址后边的几个字节(重要)//两个数值是自己写好程序后 调试程序时 手动找出来的 不知道怎么动态获得 待大牛看后 指点迷津//计算一下代码需要的内存长度 再加上至少有返回的指令的长度 此时即为2//多了也没事 自动填充为 CCmemcpy(begin+sizeof(mov_eax)*2+sizeof(push_old_eop),(PVOID)start_qf,lenofcode+2);
//重要一步 修改eop入口点地址为新加节的rvaOPTION-&AddressOfEntryPoint=newsec-&VirtualA
//修改入口点地址到新加节的rva此时解密也结束了第六步收尾工作首先了解一点知识 摘在网络为了提高速度,系统将文件的数据页面进行高速缓存,并且在对文件的映射视图进行操作时不立即更新文件的磁盘映像。如果需要确保你的更新被写入磁盘,可以强制系统将修改过的数据的一部分或全部重新写入磁盘映像中,方法是调用F l u s h Vi e w O f F i l e函数:BOOL FlushViewOfFile(
PVOID pvAddress,
SIZE_T dwNumberOfBytesToFlush);第一个参数是包含在内存映射文件中的视图的一个字节的地址。该函数将你在这里传递的地址圆整为一个页面边界值。第二个参数用于指明你想要刷新的字节数。系统将把这个数字向上圆整,使得字节总数是页面的整数。1 "对文件的映射视图进行操作时不立即更新文件的磁盘映像" 那么何时更新?我程序正常退出前一定会更新吧?如果程序意外结束(比如电脑死机)那是不是就可能无法将更改写入磁盘?1、在UnmapViewOfFile、CloseHandle和系统回收物理内存的时候写入磁盘。当进程结束时(包括正常和异常),系统会自动关闭该进程打开的所有Handle,所以会写入磁盘。除非是内核代码异常,导致死机,这时才可能没有写入。2 是不是只要程序不意外结束,我们就没使用FlushViewOfFile的必要?否则请问在什么情况下有必要使用它?2、FlushViewOfFile是为了实现程序自己控制写入磁盘而提供的,当你真正遇到这种需求的时候才能体会到它的价值。本程序实现的代码如下BOOL success = FlushViewOfFile(Pimage,FileSize);
//将写入文件映射缓冲区的所有数据都刷新到磁盘if (!success){}success = UnmapViewOfFile(Pimage); //在当前应用程序的内存地址空间解除对一个文件映射对象的映射
//lpBaseAddress Long,指定要解除映射的一个文件映射的基准地址。这个地址是早先用MapViewOfFile函数获得的CloseHandle(hMap);到此 结束了程序架构主要是强哥的思路 好多问题也是强哥解决 我慢慢消化的 不过也有自己发现的一些新的问题和解决方法同时还感谢老牛孜孜不倦 累死不疲的淳淳教诲和督促 也帮我解决了不少的问题感慨 团队就是好
声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至: 进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。

我要回帖

更多关于 instasize怎么取消购买 的文章

 

随机推荐