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函数,大概就是酱紫
选择第一个函数PrintAddr来查看其中的实现代码。根据其中的注释就可以看出来输出是的打印g_Table和g_Table2。
而对于其中的这两个参数只有类似如下数组地址值,所以打印就是数组的地址。
.text:00000400 LDR R2, =(g_Table_ptr - 0x1FE4)
.text:00000404 LDR R2, [R3,R2] ; g_Table
回到main函数中,重新选择InitTable函数,在图表视图中可以看到此函数实现了两个循环,具体是哪种循环暂不得知,首先查看第一个循环,从开始的循环赋值和比较开始,
在左侧的循环体中,获取的是循环变量的值,在STR指令中,把循环变量存入到了R3(g_Table数组的地址值),R2、*4代表了int型的四字节长度,所以此处意义是array[i] = i。按照循环变量的增长值按顺序存入到了数组中。
当循环变量大于99时,跳出循环走到右边的步骤,获取R3的地址值,R3则代表的是一串字符串,其后使用puts输出,利用puts是输出后,会自动在其后添加换行符。然后再对循环体重赋值。
继续查看第二个循环体,由于跟第一个循环一致,不在细看。
分析完InitTable函数后,可以得知,这是一个对全局数组进行赋值的操作。也许后面会用到这个数组。回到main函数中,其后调用了两次write函数,对每个write函数进行两个参数的引用。查看write函数。
函数跟InitTable其中对数组的操作类似,都是根据参数进入数组的赋值,如下的对write函数中的第一个参数作为数组的下标,以第二个参数作为需要重新赋值的数组值。array[var_8] = var_c。
在去选择search函数,查看函数实现和逻辑,其中传入参数var_10为200,进入循环判断是否大于99,进入循环体,获取数组的下标对应的值,来和传入的参数进行对比不相同则跳转继续循环。相同则跳出循环,获取数组下标值返回,类似如下
R1 = array[var_8] = array[i]
R3 = var_10 = 200
if array[var_8] == var_10:
return var_8
最后的main函数,重新调用了write函数,利用search的返回值来判断是否是-1,CMN是做负数对比。而R3的负数来源search函数的大于99后仍然没有找到返回值时,返回-1。