博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
全局变量反汇编与重定位
阅读量:6957 次
发布时间:2019-06-27

本文共 6667 字,大约阅读时间需要 22 分钟。

目录


title: 全局变量反汇编与重定位

date: 2019/02/23 21:10:08
toc: true
---

全局变量反汇编与重定位

引入

本文完整代码地址

思考这样一个问题,全局变量是怎么存储的,怎么使用的,反汇编后是什么样子的?

  1. 最理想的取地址应该是这样的,但是并没有这样的指令,操作数不可能是一个32位的数

    ldr r0,[a的地址]
  2. 所以我们还想这样,还需要 将 r1 赋值32位的地址..所以单纯的赋值没有办法实现这个操作

    ldr r0,[r1]
  3. 也就是需要这么做

    ldr r0,[pc,offset] ;lable1lable1:  addr_vallabel2_addr_val:  val

    mark

我们写这样一段代码测试一下.

#include 
int a=0;int b=1;int test(int c){ c=c+1; printf("hello %d",c); return c;}typedef int (*funpt)(int);funpt pt =&test;int main(){ a=3; b=b+1; test(a); pt(b);}

makefiel如下,反汇编中加入c语言信息,加入-S选项,cc中加入-g选项

all:    arm-linux-gcc    -g  -o o.out globl_var.c -Wl,-Map=gcc.map    arm-linux-objdump -D -S  o.out>o.disclaen:    rm *.out

nopie分析

一般我们编译的时候都是nopie,pie我是在编译uboot时候了解到的,本篇文章也是关于uboot重定位分析的子章节

MAP

我们先来看下map文件的地址,有助于后续的分析

.text       0x00008380                test.bss        0x000105f8                a.data       0x000105f0                pt            0x000105ec                b

普通变量

main函数入手,先从[pc, #88]的地方取得一个值,再从这个值所表示的地址中取值

a=3;    83cc:   e59f2050    ldr r2, [pc, #80]   ; 8424 
83d0: e3a03003 mov r3, #3 ; 0x3 83d4: e5823000 str r3, [r2] 8424: 000105f8 .word 0x000105f8 8428: 000105ec .word 0x000105ec 842c: 000105f0 .word 0x000105f0 000105ec
: 105ec: 00000001 .word 0x00000001000105f0
: 105f0: 00008380 .word 0x00008380Disassembly of section .bss:000105f4
: 105f4: 00000000 .word 0x00000000000105f8
: 105f8: 00000000 .word 0x00000000

从代码上可以看出来8424这个地方存储的就是变量的地址,也就是这么一个示意图

mark

可以看到a所表示的地址的值,确实是0,实际上这个是存在bss段的.

接着来看代码b=b+1,多了一个取值的步骤

b=b+1;    83d8:   e59f3048    ldr r3, [pc, #72]   ; 8428 
83dc: e5933000 ldr r3, [r3] 83e0: e2832001 add r2, r3, #1 ; 0x1 83e4: e59f303c ldr r3, [pc, #60] ; 8428
83e8: e5832000 str r2, [r3] 8424: 000105f8 .word 0x000105f8 8428: 000105ec .word 0x000105ec 842c: 000105f0 .word 0x000105f0 000105ec
: 105ec: 00000001 .word 0x00000001

指针变量

接着来看下函数指针pt的处理

pt(b);    ; 取出指针的地址,这个和我们普通变量操作中先取出变量的地址是一样的    83fc:   e59f3028    ldr r3, [pc, #40]   ; 842c 
; 获取变量的值,也就是指针的值,这里就是test的地址值了 ; 可以看到 [000105f0]=00008380 确实是 00008380
: 8400: e5932000 ldr r2, [r3] ;取出变量b的地址 然后取出b的值 8404: e59f301c ldr r3, [pc, #28] ; 8428
8408: e5933000 ldr r3, [r3] ; 传递为第一个参数 840c: e1a00003 mov r0, r3 8410: e1a0e00f mov lr, pc ;r2在上面赋值就是test的值 8414: e12fff12 bx r2 842c: 000105f0 .word 0x000105f0 000105f0
: 105f0: 00008380 .word 0x00008380 00008380
:

print函数

在函数中调用了库函数,这里也是使用了相对跳转了

printf("hello %d",c);839c:   e59f0018    ldr r0, [pc, #24]   ; 83bc 
83a0: e51b1008 ldr r1, [fp, #-8]83a4: ebffffc5 bl 82c0 <_init+0x48>

pie分析

接下去的分析都是针对重定位uboot的,与一般的程序没有关系了,不属于全局变量反汇编的分析

MAP

.text       0x00008380                test.bss        0x000105f8                a.data       0x000105f0                pt            0x000105ec                b// 上面是nopie 下面是pie的.text   0x000005f8                test.data   0x0000887c                pt.data   0x00008878                b.bss    0x00008884                a

汇编方式

加入pie选项和其实发现,单纯的这段maintest代码是一致的

mark

mark

地址分析

69c:   00008884    .word   0x00008884      ;存放的a的地址的lable 6a0:   00008878    .word   0x00008878      ;存放的b的地址的lable 6a4:   0000887c    .word   0x0000887c      ;存放的pt的地址的lable

搜索这几个地址值69c6a06a4

00000400 <.rel.dyn>: ;a 420:   0000069c    muleq   r0, ip, r6 424:   00000017    andeq   r0, r0, r7, lsl r0 ;b 428:   000006a0    andeq   r0, r0, r0, lsr #13 42c:   00000017    andeq   r0, r0, r7, lsl r0 ;pt 430:   000006a4    andeq   r0, r0, r4, lsr #13 434:   00000017    andeq   r0, r0, r7, lsl r0  450:   0000887c    andeq   r8, r0, ip, ror r8 454:   00000017    andeq   r0, r0, r7, lsl r0

同时,还有一个关键的东西,就是指针的值是个地址的时候,他的值也会出现在这个表里面

450:   0000887c    andeq   r8, r0, ip, ror r8 454:   00000017    andeq   r0, r0, r7, lsl r0

这是什么意思呢

当指针的值是个地址的时候,当重定位之后,这个地址应该同样加上偏移.

uboot的pie

.bss           0x000ae4e0        0x4 board/samsung/smdk2410/libsmdk2410.o                0x000ae4e0                a .text          0x000560dc      0x240 board/samsung/smdk2410/libsmdk2410.o                0x00056278                main2                0x00056258                test.data          0x0006adfc        0x8 board/samsung/smdk2410/libsmdk2410.o                0x0006adfc                b                0x0006ae00                pt

变量分析

00056278 
: 56278: e92d4010 push {r4, lr} ;取出b的地址 5627c: e59f402c ldr r4, [pc, #44] ; 562b0
;r4=0006adfc是b的地址 ;取出a的地址 56280: e59f302c ldr r3, [pc, #44] ; 562b4
56284: e5942000 ldr r2, [r4] 56288: e3a01003 mov r1, #3 ; 0x3 5628c: e2822001 add r2, r2, #1 ; 0x1 56290: e1a00001 mov r0, r1 56294: e5831000 str r1, [r3] 56298: e5842000 str r2, [r4] 5629c: ebffffed bl 56258
; pt(b) 562a0: e5940000 ldr r0, [r4] 562a4: e1a0e00f mov lr, pc ;到这里为止,r4依然是b的地址,也就是说 pt的地址就是b后面,pt的寻址都是按照b来的 ;手动计算一下 r4+4=6ae00 这确实是pt的实际地址 ; 0006ae00
: ; 6ae00: 00056258 .word 0x00056258 562a8: e594f004 ldr pc, [r4, #4] 562ac: e8bd8010 pop {r4, pc}

我们来看下具体的地址信息

;----------------------------------------------------------------------      562b0:   0006adfc    .word   0x0006adfc ;这个存的是b的地址   562b4:   000ae4e0    .word   0x000ae4e0 ;这个存的是a的地址   ; 这里没有lable存储着pt的地址,程序依靠先找到b的地址,b地址下一个偏移就是pt的地址   ; pt里面的值也是个地址   0006ae00 
: 6ae00: 00056258 .word 0x00056258

接下来的就是应该重定位的变量信息,也就是lable和地址,可以看到lable和指针都出现了这张表里面

;存放b的lable的地址   71854:   000562b0    .word   0x000562b0   71858:   00000017    .word   0x00000017   ;存放a的lable的地址   7185c:   000562b4    .word   0x000562b4   71860:   00000017    .word   0x00000017   ;这里没有存放pt的lable地址 ,依靠b的地址来寻找   ;pt的值也是个地址值,那么这个地址也应该处理   72c1c:   0006ae00    .word   0x0006ae00   72c20:   00000017    .word   0x00000017

小结重定位数据段

也就是说,这个特殊的段<.rel.dyn>应该存放有所有值是地址的单元的地址.

反汇编文件可以看成数据段加指令段,这里考虑数据段

0000: ........xxxx: val     当val表示的是一个地址的时候,现在有两种情况

也就是说包含了

  • lable 的地址,存放的是全局变量的地址
  • 指针的地址,这个指针存放的是个地址

有了上面的<.rel.dyn>段重定位数据段就很方便了,将里面的地址挑出来,对其值和其存放的地址都加上偏移即可

  1. 取出a的地址,此时a的地址应该加上offset
  2. a的地址怎么取的,也是从一个lable中取的,这个lable也是经过offset的了
  3. 当a的值是个地址,比如是个函数指针,这个函数指针的值也应该加上offset,才是新定位的函数地址

mark

总结起来一句话

*(adr+offset)=*(adr+offset)+offset

参考文章

转载于:https://www.cnblogs.com/zongzi10010/p/10424426.html

你可能感兴趣的文章
Django:URL,Views,Template,Models
查看>>
常用工具
查看>>
Jmeter BeanShell 引用变量报错jmeter.util.BeanShellInterpreter: Error invoking bsh method: eval Parse e...
查看>>
把手机当扫描枪用
查看>>
软件质量管理
查看>>
Java中保留小数点后几位
查看>>
查找 --- 并查集
查看>>
利用 Python_tkinter 完成 2048 游戏
查看>>
洛谷P2756 飞行员配对方案问题
查看>>
vsftpd安装
查看>>
DataSet
查看>>
Python之路【第零篇】:目录篇
查看>>
so加载报错:dlopen failed: couldn't map ... Permission denied
查看>>
LCA(st算法)
查看>>
常去的网站与常用的软件
查看>>
StyleCop 官网
查看>>
BZOJ3676 [Apio2014]回文串
查看>>
UOJ131 [NOI2015] 品酒大会
查看>>
一个继承了抽象类的普通类的执行顺序
查看>>
enum 使用
查看>>