​ 在做题的时候, ida中很多指针看不懂,就很尴尬,需要再好好学习下, 不过还是多积累,遇到题目的时候每次都进行分析,后面就都慢慢熟悉了,(相应的可以根据反汇编代码写源代码,从开发、正向的角度来看)

以一道题目为例子,学习下指针等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
unsigned __int64 add_canvas()
{
__int64 v0; // rbx
int v2; // [rsp+Ch] [rbp-24h] BYREF
int v3; // [rsp+10h] [rbp-20h] BYREF
int idx; // [rsp+14h] [rbp-1Ch]
unsigned __int64 v5; // [rsp+18h] [rbp-18h]

v5 = __readfsqword(0x28u);
idx = read_idx();
if ( canvas[idx] )
{
puts("Invalid index");
}
else
{
canvas[idx] = malloc(0x20uLL);
v2 = 0;
v3 = 0;
printf("Enter canvas width (1-255): ");
__isoc99_scanf("%hhd", &v2);
printf("Enter canvas height (1-255): ");
__isoc99_scanf("%hhd", &v3);
if ( (unsigned int)(v2 * v3) <= 0xFF )
{
v0 = canvas[idx]; //v0获取canvas画布的堆块的地址,
*(_QWORD *)(v0 + 8) = malloc((unsigned int)(v2 * v3 + 1));
//v0+8,然后强制类型转换,再解引用,
//_QWORD 64位 word
*(_BYTE *)canvas[idx] = v2; // canvas这里也是QWORD类型(其实可以统一替换成v0的
*(_BYTE *)(canvas[idx] + 1LL) = v3;// 所以+1 是+1 byte
*(_DWORD *)(canvas[idx] + 16LL) = 0;
*(_QWORD *)(canvas[idx] + 24LL) = 0LL;
puts("Done");
}
else
{
puts("Too big");
free((void *)canvas[idx]);
canvas[idx] = 0LL;
}
}
return v5 - __readfsqword(0x28u);
}

chatgpt

在 IDA Pro 中,”_DWORD”、”_QWORD”、”_BYTE” 等标识符通常表示不同的数据类型或数据大小,用于帮助分析和标识反汇编代码中的数据。这些标识符通常与数据类型的大小有关,以下是它们的一般含义:

  1. “_DWORD”:代表一个32位的双字(Double Word),通常对应于一个32位整数。在汇编和反汇编中,双字通常由4个字节组成。
  2. “_QWORD”:代表一个64位的四字(Quad Word),通常对应于一个64位整数。在汇编和反汇编中,四字通常由8个字节组成。
  3. “_BYTE”:代表一个8位的字节(Byte),通常对应于一个字节。在汇编和反汇编中,字节通常由一个字节组成,用于表示较小的数据。
  4. 字是16位(历史原因、兼容原因……….)

画堆块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
+---------+----------+--------------------+
| | |
| | chunk head |
| | |
+---------+----------+-----------------+--+
+---------+----------+--------------------+
| | |
| v3 v2 | v0+8 malloc canvas |
| | |
+---------+----------+-----------------+--+
+---------+----------+--------------------+
| | |
| | |
| | |
+---------+----------+-----------------+--+





画布



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int draw()
{
int result; // eax
int i; // [rsp+8h] [rbp-8h]
int idx; // [rsp+Ch] [rbp-4h]

idx = read_idx();
if ( !canvas[idx] )
return puts("Invalid index");
puts("Enter your picture (`width` chars in `height` lines): ");
for ( i = 0; ; ++i )
{
result = *(unsigned __int8 *)(canvas[idx] + 1LL); //height
if ( i >= result )
break;
read( //画一行 width
0,
(void *)(*(_QWORD *)(canvas[idx] + 8LL) + i * *(unsigned __int8 *)canvas[idx]),
*(unsigned __int8 *)canvas[idx] + 1);
}// *(_QWORD *)(canvas[idx] + 8LL) 是画布的地址,
//i * *(unsigned __int8 *)canvas[idx] 是i * 宽
//*(unsigned __int8 *)canvas[idx] + 1 是先取了宽,然后+1,
// 所以输入0 8 1 的话,就是读入一行,读入9个字符(包括结束符号)
// 读入地址就是开头呀
return result;
}

0 8 1

结束符号EOF包括\n \0?

函数名:read

头文件:<io.h>

函数原型: int read(int handle,void *buf,int len);

功能:用于读取打开文件的内容

参数:int handle 为要读取的文件

​ void *buf 为要将读取的内容保存的缓冲区

​ int len 读取文件的长度

返回值:返回实际读取的字节数

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <stdlib.h>

void main()
{
char *canvas[5];
char *str;
int addr;
canvas[0] = malloc(0x20);
addr = canvas[0];
addr = 1;

}

指针和long int存储的有区别吗? 有区别的,

如果是long int的话

*(uintptr_t *)(x+8) = malloc(0x30); 先把地址+8,然后强制类型转换成指针,然后解引用