滴水逆向-指针1

 

 

 

 

 

 

 

 

 

 

 

 相关练习和测试代码

C指针

1."带*类型" 的特征探测:宽度        

宽度探测

带一个*的探测

源代码

#include "stdafx.h"    
#include <string.h>

void fun()
{
    char* a = (char*)1;
    short* b = (short*)2;
    int* c =(int*)3;

    printf("%d %d %d\n",a,b,c);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}            

反汇编代码

9:        char* a = (char*)1;
0040B818   mov         dword ptr [ebp-4],1
10:       short* b = (short*)2;
0040B81F   mov         dword ptr [ebp-8],2
11:       int* c =(int*)3;
0040B826   mov         dword ptr [ebp-0Ch],3

上述显示都是站4个字节

带两个*的探测

源代码
#include "stdafx.h"    
#include <string.h>

void fun()
{
    char** a = (char**)1;
    short** b = (short**)2;
    int** c =(int**)3;

    printf("%d %d %d\n",a,b,c);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}

反汇编代码

9:        char** a = (char**)1;
0040B818   mov         dword ptr [ebp-4],1
10:       short** b = (short**)2;
0040B81F   mov         dword ptr [ebp-8],2
11:       int** c =(int**)3;
0040B826   mov         dword ptr [ebp-0Ch],3

上述显示还是都站4个字节


带两个以上*的探测

源代码
#include "stdafx.h"    
#include <string.h>

void fun()
{
    char******* a = (char*******)1;
    short******* b = (short*******)2;
    int******* c =(int*******)3;

    printf("%d %d %d\n",a,b,c);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}


反汇编代码

9:        char******* a = (char*******)1;
0040B818   mov         dword ptr [ebp-4],1
10:       short******* b = (short*******)2;
0040B81F   mov         dword ptr [ebp-8],2
11:       int******* c =(int*******)3;
0040B826   mov         dword ptr [ebp-0Ch],3

上述显示还是都站4个字节

结论:
不管什么类型,不管带多少个*,她们所站的字节大小都是4个字节;

        
                
2."带*类型"的特征探测:声明            

上述1题目中已经探测了,任何类型都可以带*,加了*就是新类型,然后可以加很多个* ,而且写法是标准最好推荐的写法是类似:int* x; 这样方便阅读

结论:                            
(1)带有*的变量类型的标准写法:变量类型* 变量名                                
(2)任何类型都可以带* 加上*以后是新的类型                                
(3)*可以是任意多个                    
    
                
3."带*类型" 的特征探测:赋值            

上述1题目已经探测了,测试赋值操作;
结论:
                    
1.带*类型的变量赋值时只能使用"完整写法".                        
                        
2.带*类型的变量宽度永远是4字节,无论类型是什么,无论有几个*.                        
    
                
4."带*类型" 的特征探测:++ --        

带一个*的测试

源代码

#include "stdafx.h"    
#include <string.h>

void fun()
{
    char* a;
    short* b;
    int* c;

    a = (char*)100;
    b = (short*)100;
    c = (int*)100;
    

    a++;
    b++;
    c++;

    printf("%d %d %d\n",a,b,c);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}

运行结果:101 102 104

反汇编代码

9:        char* a;
10:       short* b;
11:       int* c;
12:
13:       a = (char*)100;
0040B818   mov         dword ptr [ebp-4],64h
14:       b = (short*)100;
0040B81F   mov         dword ptr [ebp-8],64h
15:       c = (int*)100;
0040B826   mov         dword ptr [ebp-0Ch],64h
16:
17:
18:       a++;
0040B82D   mov         eax,dword ptr [ebp-4]
0040B830   add         eax,1
0040B833   mov         dword ptr [ebp-4],eax
19:       b++;
0040B836   mov         ecx,dword ptr [ebp-8]
0040B839   add         ecx,2
0040B83C   mov         dword ptr [ebp-8],ecx
20:       c++;
0040B83F   mov         edx,dword ptr [ebp-0Ch]
0040B842   add         edx,4
0040B845   mov         dword ptr [ebp-0Ch],edx


带两个*的测试

#include "stdafx.h"    
#include <string.h>

void fun()
{
    char** a;
    short** b;
    int** c;

    a = (char**)100;
    b = (short**)100;
    c = (int**)100;
    

    a++;
    b++;
    c++;

    printf("%d %d %d\n",a,b,c);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}    

运行结果:104 104 104


反汇编代码

9:        char** a;
10:       short** b;
11:       int** c;
12:
13:       a = (char**)100;
0040B818   mov         dword ptr [ebp-4],64h
14:       b = (short**)100;
0040B81F   mov         dword ptr [ebp-8],64h
15:       c = (int**)100;
0040B826   mov         dword ptr [ebp-0Ch],64h
16:
17:
18:       a++;
0040B82D   mov         eax,dword ptr [ebp-4]
0040B830   add         eax,4
0040B833   mov         dword ptr [ebp-4],eax
19:       b++;
0040B836   mov         ecx,dword ptr [ebp-8]
0040B839   add         ecx,4
0040B83C   mov         dword ptr [ebp-8],ecx
20:       c++;
0040B83F   mov         edx,dword ptr [ebp-0Ch]
0040B842   add         edx,4
0040B845   mov         dword ptr [ebp-0Ch],edx

带两个以上*的测试

源代码

#include "stdafx.h"    
#include <string.h>

void fun()
{
    char********* a;
    short********* b;
    int********* c;

    a = (char*********)100;
    b = (short*********)100;
    c = (int*********)100;
    

    a++;
    b++;
    c++;

    printf("%d %d %d\n",a,b,c);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}

反汇编代码

9:        char********* a;
10:       short********* b;
11:       int********* c;
12:
13:       a = (char*********)100;
0040B818   mov         dword ptr [ebp-4],64h
14:       b = (short*********)100;
0040B81F   mov         dword ptr [ebp-8],64h
15:       c = (int*********)100;
0040B826   mov         dword ptr [ebp-0Ch],64h
16:
17:
18:       a++;
0040B82D   mov         eax,dword ptr [ebp-4]
0040B830   add         eax,4
0040B833   mov         dword ptr [ebp-4],eax
19:       b++;
0040B836   mov         ecx,dword ptr [ebp-8]
0040B839   add         ecx,4
0040B83C   mov         dword ptr [ebp-8],ecx
20:       c++;
0040B83F   mov         edx,dword ptr [ebp-0Ch]
0040B842   add         edx,4
0040B845   mov         dword ptr [ebp-0Ch],edx

运行结果:104 104 104

结论:                            
                            
1.不带*类型的变量,++或者--  都是加1 或者减1                                            
2.带*类型的变量,可是进行++ 或者 --的操作                                                    
3.带*类型的变量,++ 或者 -- 新增(减少)的数量是去掉一个*后变量的宽度                            

                
5."带*类型" 的特征探测:加上/减去 一个整数                

带一个*的测试

源代码

#include "stdafx.h"    
#include <string.h>

void fun()
{
    char* a;
    short* b;
    int* c;

    a = (char*)100;
    b = (short*)100;
    c = (int*)100;
    
    a = a + 6;
    b = b + 6;
    c = c + 6;


    printf("%d %d %d\n",a,b,c);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}    

运行结果:106 112 124

反汇编代码

9:        char* a;
10:       short* b;
11:       int* c;
12:
13:       a = (char*)100;
0040B818   mov         dword ptr [ebp-4],64h
14:       b = (short*)100;
0040B81F   mov         dword ptr [ebp-8],64h
15:       c = (int*)100;
0040B826   mov         dword ptr [ebp-0Ch],64h
16:
17:       a = a + 6;
0040B82D   mov         eax,dword ptr [ebp-4]
0040B830   add         eax,6
0040B833   mov         dword ptr [ebp-4],eax
18:       b = b + 6;
0040B836   mov         ecx,dword ptr [ebp-8]
0040B839   add         ecx,0Ch
0040B83C   mov         dword ptr [ebp-8],ecx
19:       c = c + 6;
0040B83F   mov         edx,dword ptr [ebp-0Ch]
0040B842   add         edx,18h
0040B845   mov         dword ptr [ebp-0Ch],edx


带两个*的测试

源代码

#include "stdafx.h"    
#include <string.h>

void fun()
{
    char** a;
    short** b;
    int** c;

    a = (char**)100;
    b = (short**)100;
    c = (int**)100;
    
    a = a + 6;
    b = b + 6;
    c = c + 6;


    printf("%d %d %d\n",a,b,c);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}

运行结果:124 124 124

反汇编代码

9:        char** a;
10:       short** b;
11:       int** c;
12:
13:       a = (char**)100;
0040B818   mov         dword ptr [ebp-4],64h
14:       b = (short**)100;
0040B81F   mov         dword ptr [ebp-8],64h
15:       c = (int**)100;
0040B826   mov         dword ptr [ebp-0Ch],64h
16:
17:       a = a + 6;
0040B82D   mov         eax,dword ptr [ebp-4]
0040B830   add         eax,18h
0040B833   mov         dword ptr [ebp-4],eax
18:       b = b + 6;
0040B836   mov         ecx,dword ptr [ebp-8]
0040B839   add         ecx,18h
0040B83C   mov         dword ptr [ebp-8],ecx
19:       c = c + 6;
0040B83F   mov         edx,dword ptr [ebp-0Ch]
0040B842   add         edx,18h
0040B845   mov         dword ptr [ebp-0Ch],edx



带两个以上*的测试

源代码

#include "stdafx.h"    
#include <string.h>

void fun()
{
    char********* a;
    short********* b;
    int********* c;

    a = (char*********)100;
    b = (short*********)100;
    c = (int*********)100;
    
    a = a + 6;
    b = b + 6;
    c = c + 6;


    printf("%d %d %d\n",a,b,c);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}

运行结果:124 124 124

反汇编代码

9:        char********* a;
10:       short********* b;
11:       int********* c;
12:
13:       a = (char*********)100;
0040B818   mov         dword ptr [ebp-4],64h
14:       b = (short*********)100;
0040B81F   mov         dword ptr [ebp-8],64h
15:       c = (int*********)100;
0040B826   mov         dword ptr [ebp-0Ch],64h
16:
17:       a = a + 6;
0040B82D   mov         eax,dword ptr [ebp-4]
0040B830   add         eax,18h
0040B833   mov         dword ptr [ebp-4],eax
18:       b = b + 6;
0040B836   mov         ecx,dword ptr [ebp-8]
0040B839   add         ecx,18h
0040B83C   mov         dword ptr [ebp-8],ecx
19:       c = c + 6;
0040B83F   mov         edx,dword ptr [ebp-0Ch]
0040B842   add         edx,18h
0040B845   mov         dword ptr [ebp-0Ch],edx


结论:                    
                            
1.带*类型的变量可以加、减一个整数,但不能乘或者除.                            
                            
2.带*类型变量与其他整数相加或者相减时:        
                                            
    带*类型变量 + N  =  带*类型变量 + N*(去掉一个*后类型的宽度)                                            
    带*类型变量 - N  =  带*类型变量 - N*(去掉一个*后类型的宽度)                        

所以计算结果就是:带*变量的值加上或者减去去掉一个*之后的类型宽度乘以一个整数;

例如:
    上面测试加法的时候,两个以上*的计算操作:100+4x6=124
    上面测试减法的时候,两个以上*的计算操作:100-4x6=76
                
6."带*类型" 的特征探测:求差值        

带一个*的测试

源代码

#include "stdafx.h"    
#include <string.h>

void fun()
{
    char* a;
    char* b;

    a = (char*)200;
    b = (char*)100;
    
    int c = a - b;


    printf("%d\n",c);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}    

运行结果:100

反汇编代码

9:        char* a;
10:       char* b;
11:
12:       a = (char*)200;
0040B818   mov         dword ptr [ebp-4],0C8h
13:       b = (char*)100;
0040B81F   mov         dword ptr [ebp-8],64h
14:
15:       int c = a - b;
0040B826   mov         eax,dword ptr [ebp-4]
0040B829   sub         eax,dword ptr [ebp-8]
0040B82C   mov         dword ptr [ebp-0Ch],eax


带两个*的测试

源代码

#include "stdafx.h"    
#include <string.h>

void fun()
{
    char** a;
    char** b;

    a = (char**)200;
    b = (char**)100;
    
    int c = a - b;


    printf("%d\n",c);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}            

运行结果:25

反汇编代码

9:        char** a;
10:       char** b;
11:
12:       a = (char**)200;
0040B818   mov         dword ptr [ebp-4],0C8h
13:       b = (char**)100;
0040B81F   mov         dword ptr [ebp-8],64h
14:
15:       int c = a - b;
0040B826   mov         eax,dword ptr [ebp-4]
0040B829   sub         eax,dword ptr [ebp-8]
0040B82C   sar         eax,2
0040B82F   mov         dword ptr [ebp-0Ch],eax


带两个以上*的测试

源代码


#include "stdafx.h"    
#include <string.h>

void fun()
{
    char************ a;
    char************ b;

    a = (char************)200;
    b = (char************)100;
    
    int c = a - b;


    printf("%d\n",c);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}    

运行结果:25

反汇编代码

9:        char************ a;
10:       char************ b;
11:
12:       a = (char************)200;
0040B818   mov         dword ptr [ebp-4],0C8h
13:       b = (char************)100;
0040B81F   mov         dword ptr [ebp-8],64h
14:
15:       int c = a - b;
0040B826   mov         eax,dword ptr [ebp-4]
0040B829   sub         eax,dword ptr [ebp-8]
0040B82C   sar         eax,2
0040B82F   mov         dword ptr [ebp-0Ch],eax

结论:                    
                    
1.两个类型相同的带*类型的变量可以进行减法操作.                            
2.想减的结果要除以去掉一个*的数据的宽度.            

例如:
    上面的计算操作:200-100=100  100/4=25        
                
7."带*类型" 的特征探测:比较            

#include "stdafx.h"    
#include <string.h>

void fun()
{
    char************** a ;        
    char************** b ;        
        
    a = (char**************)200;        
    b = (char**************)100;        
        
    if(a>b)        
    {        
        printf("6\n");    
    }        
    else        
    {        
        printf("8\n");    
    }        
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}    
                
结论:
                    
带*的变量,如果类型相同,可以做大小的比较。                


课后练习
                    
1.char类型占几字节?char*类型占几字节?int*****占几字节?    
                    
char 占用1字节                        
(32位下)char* 站用4字节                        
(32位下)int***** 站用4字节                        
                        
                        
2char** arr[10] 占多少个字节?    

4x10=40                    
(32位下)char*** arr[10]占用40个字节                        
                            
3、自定义结构体如下:                        
                        
struct Student                        
{                        
    int x;                    
    int y;                    
};                        
                
                
正常不带*测试代码

#include "stdafx.h"    
#include <string.h>

struct student
{
    int x;
    int y;
};


void fun()
{
    student s;
    s.x = 100;
    s.y = 200;

    printf("%d %d",s.x,s.y);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}            


带一个*的测试

源代码

#include "stdafx.h"    
#include <string.h>

struct student
{
    int x;
    int y;
};


void fun()
{
    student* s;
    
    s = (student*)100;

    s++;

    printf("%d",s);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}    

运算结果;108

反汇编代码:

4:    #include "stdafx.h"
5:    #include <string.h>
6:
7:    struct student
8:    {
9:        int x;
10:       int y;
11:   };
12:
13:
14:   void fun()
15:   {
0040B800   push        ebp
0040B801   mov         ebp,esp
0040B803   sub         esp,44h
0040B806   push        ebx
0040B807   push        esi
0040B808   push        edi
0040B809   lea         edi,[ebp-44h]
0040B80C   mov         ecx,11h
0040B811   mov         eax,0CCCCCCCCh
0040B816   rep stos    dword ptr [edi]
16:       student* s;
17:
18:       s = (student*)100;
0040B818   mov         dword ptr [ebp-4],64h
19:
20:       s++;
0040B81F   mov         eax,dword ptr [ebp-4]
0040B822   add         eax,8
0040B825   mov         dword ptr [ebp-4],eax
21:
22:       printf("%d",s);
0040B828   mov         ecx,dword ptr [ebp-4]
0040B82B   push        ecx
0040B82C   push        offset string "6\n" (0042001c)
0040B831   call        printf (00401110)
0040B836   add         esp,8
23:   }
0040B839   pop         edi
0040B83A   pop         esi
0040B83B   pop         ebx
0040B83C   add         esp,44h
0040B83F   cmp         ebp,esp
0040B841   call        __chkesp (00401190)
0040B846   mov         esp,ebp
0040B848   pop         ebp
0040B849   ret


带两个*的测试

源代码

#include "stdafx.h"    
#include <string.h>

struct student
{
    int x;
    int y;
};


void fun()
{
    student** s;
    
    s = (student**)100;

    s++;

    printf("%d",s);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}            

运算结果:104

带两个以上*的测试

源代码

#include "stdafx.h"    
#include <string.h>

struct student
{
    int x;
    int y;
};


void fun()
{
    student******* s;
    
    s = (student*******)100;

    s++;

    printf("%d",s);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}            

运算结果:104

进行加上或者减去一个整数测试

带一个*测试

源代码

#include "stdafx.h"    
#include <string.h>

struct student
{
    int x;
    int y;
};


void fun()
{
    student* s;
    
    s = (student*)100;

    s = s + 2;

    printf("%d",s);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}            

运算结果:116

带两个*测试

#include "stdafx.h"    
#include <string.h>

struct student
{
    int x;
    int y;
};


void fun()
{
    student** s;
    
    s = (student**)100;

    s = s + 2;

    printf("%d",s);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}    

运算结果:108

带两个以上*测试

源代码

#include "stdafx.h"    
#include <string.h>

struct student
{
    int x;
    int y;
};


void fun()
{
    student********* s;
    
    s = (student*********)100;

    s = s + 2;

    printf("%d",s);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}            

加法:100+2x4=108
减法:100-2x4=92
                        

相减进行测试

源代码

两个以上*测试

#include "stdafx.h"    
#include <string.h>

struct student
{
    int x;
    int y;
};


void fun()
{
    student********* s1;
    student********* s2;
    int x;
    
    s1 = (student*********)200;
    s2 = (student*********)100;
    x = s1 - s2;

    printf("%d",x);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}    

运算结果:25

通过测试两个*的计算结果也是25

一个*测试

源代码

#include "stdafx.h"    
#include <string.h>

struct student
{
    int x;
    int y;
};


void fun()
{
    student* s1;
    student* s2;
    int x;
    
    s1 = (student*)200;
    s2 = (student*)100;
    x = s1 - s2;

    printf("%d",x);
}

int main(int argc, char* argv[])
{
    fun();
    return 0;
}            

运算结果:12

200-100=100  100/8=12.5 取12
8的由来是结构体里面两个整形int,所站字节数是8
                        
                        
结论:
    结构体定义带*的操作跟其他类型一样,当定义两个*以上的类型,都按照4个字节宽度进行计算,当定义一个*的时候按照结构体内部实际字节站用的计算
        
                        
                        
                        

 

posted @ 2021-08-12 17:36  皇帽讲绿帽带法技巧  阅读(134)  评论(0编辑  收藏  举报