转:Hide data inside pointers(在指针中隐藏数据)
该文介绍了如何使用指针中一些未使用的位来隐藏一些数据。
When we write C code, pointers are everywhere. We can make a little extra use of pointers and sneak in some extra information in them. To pull this trick off, we exploit the natural alignment of data in memory.
Data in memory is not stored at any arbitrary address. The processor always reads memory in chunks at the same size as its word size; and thus for efficiency reasons, the compiler assigns addresses to entities in memory as multiples of their size in bytes. Therefore on a 32 bit processor, a 4-byte int will definitely reside at a memory address that is evenly divisible by 4.
Here, I am going to assume a system where size of int and size of pointer are 4 bytes.
Now let us consider a pointer to an int. As said above, the int can be located at memory addresses 0x1000 or 0x1004 or 0x1008, but never at 0x1001 or 0x1002 or 0x1003 or any other address that is not divisible by 4.
Now, any binary number which is a multiple of 4 will end with 00.
This essentially means that for any pointer to an int, its 2 lower order bits are always zero.
Now we have 2 bits which communicate nothing. The trick here is put our data into these 2 bits, use them whenever we want and then remove them before we make any memory access by dereferencing the pointer.
Since bitwise operations on pointers don’t go well with the C standard, We will be storing the pointer as an unsigned int.
The following is a naive snippet of the code for brevity. See my github repo - hide-data-in-ptr for the full code.
void put_data(int *p, unsigned int data)
{
assert(data < );
*p |= data;
} unsigned int get_data(unsigned int p)
{
return (p & );
} void cleanse_pointer(int *p)
{
*p &= ~;
} int main(void)
{
unsigned int x = ;
unsigned int p = (unsigned int) &x; printf("Original ptr: %u\n", p); put_data(&p, ); printf("ptr with data: %u\n", p);
printf("data stored in ptr: %u\n", get_data(p)); cleanse_pointer(&p); printf("Cleansed ptr: %u\n", p);
printf("Dereferencing cleansed ptr: %u\n", *(int*)p); return ;
}
This will give the following output:
Original ptr: 3216722220
ptr with data: 3216722223
data stored in ptr: 3
Cleansed ptr: 3216722220
Dereferencing cleansed ptr: 701
We can store any number that can be represented by 2 bits in the pointer. Using put_data(), the last 2 bits of the pointer are set as the data to be stored. This data is accessed using get_data(). Here, all bits except the last 2 bits are overwritten as zeroes there by revealing our hidden data.
cleanse_pointer() zeroes out the last 2 bits, making the pointer safe for dereferencing. Note that while some CPUs like Intel will let us access unaligned memory locations, certain others like ARM CPU will fault. So, always remember to keep the pointer pointed to an aligned location before dereferencing.
Is this used anywhere in the real world?
Yes, it is. See the implementation of Red Black Trees in the Linux kernel (link).
The node of the tree is defined using:
struct rb_node {
unsigned long __rb_parent_color;
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
Here unsigned long __rb_parent_color stores:
1. the address of the parent node
2. the node’s color.
The color is represented as 0 for Red and 1 for Black.
Just like in the earlier example, this data is sneaked into the ‘useless’ bits of the parent pointer.
Now see, how the parent pointer and the color information is accessed:
/* in rbtree.h */
#define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3))/* in rbtree_augmented.h */
#define __rb_color(pc) ((pc) & 1)
#define rb_color(rb) __rb_color((rb)->__rb_parent_color)
转:Hide data inside pointers(在指针中隐藏数据)的更多相关文章
- 在图像中隐藏数据:用 Python 来实现图像隐写术
什么是“隐写术”? 隐写术是将机密信息隐藏在更大的信息中,使别人无法知道隐藏信息的存在以及隐藏信息内容的过程.隐写术的目的是保证双方之间的机密交流.与隐藏机密信息内容的密码学不同,隐写术隐瞒了传达消息 ...
- NOPI读取模板导出(Excel中追加数据)
在Controller里,我们定义一个FileResult的Action,返回值是一个文件形式被浏览器下载下来. [HttpGet] public FileResult ExportProductLi ...
- Java生鲜电商平台-SpringCloud微服务开发中的数据架构设计实战精讲
Java生鲜电商平台-SpringCloud微服务开发中的数据架构设计实战精讲 Java生鲜电商平台: 微服务是当前非常流行的技术框架,通过服务的小型化.原子化以及分布式架构的弹性伸缩和高可用性, ...
- 访问cv::Mat中的数据时遇到的指针类型问题
在用Opencv的时候由于下图原本的图像尺寸是1111*1111,要进行resize,代码如下: cv::Mat img = cv::imread("//Users//apple//td3/ ...
- 聚集表(clustered table)data page中的数据行可以无序
误区 一直以为只要一个表含有聚集索引,那么在data page中的数据行是排序的.比如原来data page中有1.2.4.5.6这样四条记录,那么我要插入3这条记录,应该是先将456三条记录往后移, ...
- [MySQL]load data local infile向MySQL数据库中导入数据时,无法导入和字段不分离问题。
利用load data将文件中的数据导入数据库表中的时候,遇到了两个问题. 首先是load data命令无法执行的问题: 命令行下输入load data local infile "path ...
- Web网页中动态数据区域的识别与抽取 Dynamical Data Regions Identification and Extraction in Web Pages
Web网页中动态数据区域的识别与抽取 Dynamical Data Regions Identification and Extraction in Web Pages Web网页中动态数据区域的识别 ...
- load data导txt文件进mysql中的数据
1.实验内容: 利用SQL语句“load data ”将“.txt”文本文件中的数据导入到mysql中 2.实验过程: 首先我创了一个txt(也可以是其他的),设置其编码为utf-8,在windows ...
- 报错:此版本的SQL Server Data Tools与此计算机中安装的数据库运行时组件不兼容
在Visual Studio 2012中使用Entity Framework,根据模型生成数据库时,报如下错误: 无法在自定义编辑器中打开Transact-SQL文件此版本的SQL Server Da ...
随机推荐
- 数据库操作(C#)
数据库在软件开发中发挥着举足轻重的作用,基本上所有的大项目都会用到数据库.ADO .Net是一组向.Net程序员公开数据访问服务的类,其主要分为数据提供程序(Data Provider)和数据集(Da ...
- rm: Argument list too long
rm -rf /testdir/* -bash: /bin/rm: Argument list too long 解决: cd /testdir/; ls | xargs rm -rf
- c#输出、输入练习
//输出 Console.WriteLine("这是一行文字"); 自动回车的. Console.Write("Hello world"); 不带回车的. ...
- 0801 am使用tp框架对数据库增删改查
增添数据,3种方法 function Text3() { $m=D("info"); //1.使用数组 $attr = array( "code"=>&q ...
- .net委托(转载)
一.什么是委托? 委托就是定义一个 对于方法的引用,类似于c++中的函数指针.委托是用来将方法作为参数 传递进入其它方法的, 委托的格式? 修饰符1 delegate 修饰符2 委托类型名(变量n ...
- java获取系统信息
public class SystemInfo { public static void main(String[] args) { //系统属性 Properties prop = System.g ...
- C++ map使用(基于RBTree)
一.insert ◦1)用insert函数插入pair数据 ◦map<int, string> mapStudent; ◦mapStudent.insert(pair<int, st ...
- Oracle11G R2用exp无法导出空表解决方法
在11G R2中有个新特性,当表无数据时,不分配segment,以节省空间Oracle当然在执行export导出时,空表则无法导出,但是还是有解决办法的: 解决方法: 一.insert一行,再roll ...
- TypeScript 0.9.1 发布,新增 typeof 关键字
TypeScript 0.9.1 发布了,该版本提升了编译器和语言的性能,增加新的语言特性 typeof ,更好的 this 处理等.详细介绍请看发行说明. TypeScript 是微软新推出的一种语 ...
- Nim教程【二】
第一篇教程1秒内就被管理员从首页踢掉了 管理员嫌内容太少,没有含金量,这次多写一些. 这应该是国内第一个关于Nim入门的系列教程 好,闲话休提,言归正传 Nim介绍 Nim代码会编译成C语言的代码,再 ...