gdb(debugger)加入软件断点的本质原理分析 博客
  • 滴水逆向 等级 N0
    2020-05-21 09:08

    当我们在gdb中break OFFSET的时候,此时的这个OFFSET是一个address.gdb首先会把这个地址的一字节的value单独自己记下来(为了之后替换回original),然后把这个字节的value设置成INT3(0xcc).假设原来在OFFSET的指令是0x8345fc01(addl $0x1,-0x8(*ebp))), gdb会把这个最后一个字节的0x01记下来,然后替换成0x8345fccc.这并不是一个这种的instruction.


    OFFSET 01 #original

    OFFSET+1 fc

    OFFSET+2 45

    OFFSET+3 83


    最终替换成


    OFFSET cc #breakpoint instered

    OFFSET+1 fc

    OFFSET+2 45

    OFFSET+3 83


    于是当我们继续进行我们这个debugged program,当遇到INT3的时候,debugger program就会trap进kernel,随后kernel就会通过信号来告知对应的gdb.gdb随后就会把这个OFFSET上的字节用他之前存储的那个original value来替换,并且把EIP的instruction potiner移动到OFFSET,并且重新开始执行OFFSET所在位置的指令。之所以要移动EIP,是因为当CPU执行了INT3之后,此时的EIP已经自动加了1个字节了。


    OFFSET cc # after breakpoint

    OFFSET+1 fc # <---- EIP points here

    OFFSET+2 45

    OFFSET+3 83


    OFFSET 01 # <--- EIP points here, after gdb restores instruction and EIP

    OFFSET+1 fc

    OFFSET+2 45

    OFFSET+3 83


    这个时候我们可以看到此时的指令已经重新编程了0x8345fc01.


    这里提一下,为什么IN3应该是1个字节。首先在x86环境下,1个字节是最小的指令长度。如果INT3比1个字节来的长,我们就会因为上面的操作覆写超过1个以上的指令,这就会产生问题。考虑如下的场景:(在Cortex-M CPUs里面,instructions要么是2个字节要么是4个字节,因此breakpoint instruction在这个CPU体系下最小长度取2个字节 https://stackoverflow.com/questions/8878716/what-is-the-difference-between-hardware-and-software-breakpoints)

    OFFSET <instruction 1, one byte> OFFSET+1 <instruction 2, one byte>


    如果假设我们要在instruction 1的地方设置断点,那么整个OFFSET就会被我们改成

    OFFSET <INT3...................

    OFFSET+1 ......................>


    如果此时一旦有指令想要跳到OFFSET+1的位置,这个位置注意并不是INT 3,而是INT 3的一部分,这就是undefined behavoir,如果我们的INT 3本身就是x86最短的1个字节的话就不会有这个问题。


    有同学肯定会问,为什么是替换字节而不是插入字节?我就不能插入这个breakpoint然后把接下来的指令都往后移吗?如果你真要做这个过程是非常复杂的,因为他会扰乱所有指令的offset,并且让所有的j*(jump)指令会跳到错误的位置


    看下面的例子:

    比如我们本来有指令为

    OFFSET <instruction 1>

    OFFSET+1 <instruction 2>


    当我们用插入的方式来设breakpoints

    OFFSET INT3
    OFFSET+1 <instruction 1> OFFSET+2 <instruction 2>


    假设我们想在instruction 1的地方加上breakpoints,如果我们沿用上面的假设改用插入,那么所有的指令往后移,那么当其他的code想要跳到OFFSET+1的时候,他本来想跳到instruction 2,但是在这里他就跳到了instruction 1,错误就产生了


    PS:

    • INT 3实际上会引发SIGTRAP信号
    • 硬件级别的断点不需要修改binary本身,他是CPU特有的技能,需要你设置一个address给他,CPU会持续的用当前的PC寄存器跟当前的运行地址做比较
    • Software Breakpoints这种改变指令的方式其实会改变整个binary的CRC,所以如果你想把你的软件变成anti-debugging,你一旦注意到你的CRC被修改,可能就表示此时你整在被debug中。同时需要注意,修改对应的opcode(替换成INT 3)只能发生在RAM里(Flash Memory不支持)
    gdb(debugger)加入软件断点的本质原理分析

  • 浏览 20
  • 点赞 1
  • 收藏 0
  • 分享 0
  • 查看云盘地址请登录
  • 点赞 已赞 收藏 已收藏
评论
    页 到
    talk top
    展开
    >