ARM数组重定向

使用如下的C代码做演示,代码是无名侠的一份数组演示代码。如下:

#include <stdio.h>
// Arrays

int g_Table[100];
int g_Table2[100];

void PrintAddr()
{
	printf("g_Table:0x%x\ng_Table2:%x\n",g_Table,g_Table2);
	
}
void InitTable()
{
	int i;
	for(i=0;i<100;i++)
		g_Table[i] = i;
	
	printf("Table1 init ok\n");
	for(i=0;i<100;i++)
		g_Table2[i] = i;
}

int search(int key)
{
	int i=0;
	for(;i<100;i++)
	{
		if(g_Table[i]==key)
			return i;
	}
	return -1;
}

int read(int x)
{
	return g_Table[x];
}
void write(int x,int value)
{
	 g_Table[x] = value;
}

int main()
{
	int idx;
	PrintAddr();
	InitTable();
	write(2,200);
	write(6,900);
	if((idx = search(200))!=-1)
		write(idx,400);
}

利用之前的makefile文件进行编译,打可执行文件丢入IDA中打开。选择main函数,大概就是酱紫

1563864556080

选择第一个函数PrintAddr来查看其中的实现代码。根据其中的注释就可以看出来输出是的打印g_Table和g_Table2。

1563865049285

而对于其中的这两个参数只有类似如下数组地址值,所以打印就是数组的地址。

.text:00000400                 LDR     R2, =(g_Table_ptr - 0x1FE4)
.text:00000404                 LDR     R2, [R3,R2] ; g_Table

回到main函数中,重新选择InitTable函数,在图表视图中可以看到此函数实现了两个循环,具体是哪种循环暂不得知,首先查看第一个循环,从开始的循环赋值和比较开始,

1563866904258

在左侧的循环体中,获取的是循环变量的值,在STR指令中,把循环变量存入到了R3(g_Table数组的地址值),R2、*4代表了int型的四字节长度,所以此处意义是array[i] = i。按照循环变量的增长值按顺序存入到了数组中。

当循环变量大于99时,跳出循环走到右边的步骤,获取R3的地址值,R3则代表的是一串字符串,其后使用puts输出,利用puts是输出后,会自动在其后添加换行符。然后再对循环体重赋值。

继续查看第二个循环体,由于跟第一个循环一致,不在细看。

1563868287872

分析完InitTable函数后,可以得知,这是一个对全局数组进行赋值的操作。也许后面会用到这个数组。回到main函数中,其后调用了两次write函数,对每个write函数进行两个参数的引用。查看write函数。

1563868846505

函数跟InitTable其中对数组的操作类似,都是根据参数进入数组的赋值,如下的对write函数中的第一个参数作为数组的下标,以第二个参数作为需要重新赋值的数组值。array[var_8] = var_c。

1563870802372

在去选择search函数,查看函数实现和逻辑,其中传入参数var_10为200,进入循环判断是否大于99,进入循环体,获取数组的下标对应的值,来和传入的参数进行对比不相同则跳转继续循环。相同则跳出循环,获取数组下标值返回,类似如下

R1 = array[var_8] = array[i]
R3 = var_10 = 200
if array[var_8] == var_10:
	return var_8

1563874211104

最后的main函数,重新调用了write函数,利用search的返回值来判断是否是-1,CMN是做负数对比。而R3的负数来源search函数的大于99后仍然没有找到返回值时,返回-1。

1563875783761





# Android逆向  

tocToc: