关于__stack_chk_guard_ptr的理解

1 篇文章 0 订阅
1 篇文章 0 订阅

过年前几天公司无事,开始做些无关的事情,比如玩玩游戏,但是我作为程序员,玩游戏的总是想找一些捷径。比如破解下加密方式,发现一些游戏漏洞等等。

如此,便是反编译了游戏的加密SO。用到的工具是IDA 和 Hopper 这俩都行。因为Mac的IDA 不能变成C。 所以用了下Hopper 还挺好用的。

好了,开始说我遇到的问题:

在静态反汇编一个SO的过程中,开头得到这样一段汇编代码:
.text:00002770                 EXPORT Java_com_happyhour_android_xt_getKey
.text:00002770
.text:00002770 var_2D8         = -0x2D8
.text:00002770 var_2D4         = -0x2D4
.text:00002770 var_2D0         = -0x2D0
.text:00002770 var_2CC         = -0x2CC
.text:00002770 var_2C8         = -0x2C8
.text:00002770 var_2C4         = -0x2C4
.text:00002770 var_2C0         = -0x2C0
.text:00002770 var_2BC         = -0x2BC
.text:00002770 var_2B8         = -0x2B8
.text:00002770 var_2B4         = -0x2B4
.text:00002770 var_2B0         = -0x2B0
.text:00002770 var_2AC         = -0x2AC
.text:00002770 var_2A4         = -0x2A4
.text:00002770 var_294         = -0x294
.text:00002770 var_274         = -0x274
.text:00002770 dest            = -0x21C
.text:00002770 var_218         = -0x218
.text:00002770 s               = -0x214
.text:00002770 var_1C          = -0x1C
.text:00002770
.text:00002770                 PUSH    {R4-R7,LR}
.text:00002772                 MOVS    R6, R3
.text:00002774                 LDR     R3, =(__stack_chk_guard_ptr - 0x277E)
.text:00002776                 LDR     R4, =0xFFFFFD3C
.text:00002778                 MOVS    R5, R0
.text:0000277A                 ADD     R3, PC ; __stack_chk_guard_ptr
.text:0000277C                 LDR     R3, [R3] ; __stack_chk_guard
.text:0000277E                 ADD     SP, R4
.text:00002780                 LDR     R1, [R3]
.text:00002782                 STR     R3, [SP,#0x2D8+var_2AC]
.text:00002784                 STR     R1, [SP,#0x2D8+var_1C]
.text:00002786                 CMP     R6, #0
.text:00002788                 BNE     loc_278C
.text:0000278A                 B       loc_2A64

前面都好理解啊,就是到哪个__stack_chk_guard_ptr 很难理解是什么意思。那这个地址放的是什么呐,在Hopper里面看到地址放的是0。

那下面那几条语句很难理解啊,把0存入了一个内存,然后把地址为0的内容放入了内存中。 这时候我怀疑这个地址是在Java 加载SO的时候动态放进去的。

查了下,果然。这是个堆栈保护区。在程序开始的时候把它的值存起来,然后在程序结束的时候,再去看一下里面的值和保存起来的值是不是一致,如果一致的话。说明该程序没有被溢出攻击,如果不一致,抛出段错误,也就是segment deafult 。


为了印证这个想法,去看下程序最后怎么做的:

.text:00002A66                 LDR     R1, [SP,#0x2D8+var_2AC]
.text:00002A68                 LDR     R2, [SP,#0x2D8+var_1C]
.text:00002A6A                 MOVS    R0, R6
.text:00002A6C                 LDR     R3, [R1]
.text:00002A6E                 CMP     R2, R3
.text:00002A70                 BEQ     loc_2A76
.text:00002A72                 BLX     __stack_chk_fail

看到没,果然进行了一次比较。 呵呵。挺有意思的。 那意思是我如果再进行堆栈溢出的时候 更改玩EIP之后。一定要把这个值还原。

===================华丽的分割线==============================

这几天下载了一些堆栈溢出的资料分析,补充一下

这个值常见的有几种方式:

1、0x000aff0d

2、随机值 

如果是第一种方式的话,即使可以精准预测保护区的位置,也会对攻击造成麻烦,因为如果是strcpy攻击的话,遇见/0会终止。 如果gets的话,遇见\n会终止。

随机值就不可能预测啊,除非你要知道随机值如何生成的。

那就不能进行攻击了么,参考了下 http://staff.ustc.edu.cn/~bjhua/courses/security/2014/readings/stackguard-bypass.pdf

这篇文章,发现其实还是可以攻击的。就是要根据一些特殊情况,他举了例子,

这种代码可能是这样的:

int func(char *msg) {

    char buf[80];

    strcpy(buf,msg);

    // toupper(buf);        // just to give func() "some" sense

    strcpy(msg,buf);

}

int main(int argv, char** argc) {

        func(argc[1]);

}

其实这种代码挺常见的, 我刚学习C的时候经常写,想修改msg的信息,然后直接不好修改。通过复制过来,然后修改完再复制过去。

这种就会有攻击的漏洞,这样通过msg填写buff溢出把msg的地址给改了。这时候有人会说这样也会修改了 canary 字段。别慌。这个判断是在程序最后才会执行。

下一个语句,把buf的内容复制到msg指向的地址空间。哈哈。这样如果把msg指向GOT的表。很容易修改了exit()函数的函数指针,比如修改成注入的shellcode。

这样函数执行完判断发现 canary修改了,执行退出函数,然后就执行了exit();然后然后然后.... 就没有然后了。


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值