ACTF Dice Game Writeup
来源:互联网 发布:淘宝怎么退货怎么邮寄 编辑:程序博客网 时间:2024/05/22 13:34
ACTF也算是结束了,浙大的那帮人脑洞也是够大的 π__π 这题目也是坑得可以。。。像我这样的渣渣只能是挑所有题目中最简单的来了。
这次的ctf好坑啊,竟然所有逆向破解题都是apk,我完全不会啊(>﹏<),只能弄到ppc了。
Dice Game 题目直接把python的源码贴了出来。源码如下:
#!/usr/bin/env python# coding: utf-8"""Yet another problem for ACTF2015.By H4sIAOzUQ1UCAwtIzUuvLFVwzkjNU9AoAHMccjKTiksSi4oy0yr1ivM1uQCpNCsJJAAAAA==COPYLEFT, ALL WRONGS RESERVED."""import randomimport timeimport sysassert sys.version_info >= (3, 2)NUM_ROUNDS = 1000SCORE_INITIAL = 100SCORE_ROUND = 10SCORE_BONUS = 2class WeBreakup(Exception): """Hmmm.. :(""" passdef play_round(scores): """Plays a single round. Returns round status and new scores.""" print('..and your guess is?') guess = input() point = random.randint(1, 6) mapping = {x: 'small' if x <= 3 else 'big' for x in range(1, 7)} if guess == mapping[point]: print('Correct. :(') guessing_correct = True # You know I'm the boss, right? score_delta = SCORE_ROUND - SCORE_BONUS scores = (scores[0] - score_delta, scores[1] + score_delta) else: print('Incorrect! :)') guessing_correct = False # You know I'm the boss, right? score_delta = SCORE_ROUND + SCORE_BONUS scores = (scores[0] + score_delta, scores[1] - score_delta) return (guessing_correct, scores)def play_game(): """Plays a game.""" print('Hey hey, you you, I wanna play a game! :)') reply = input() if reply not in ('Sure!', 'Okay!', 'With pleasure. :)'): raise WeBreakup('You bad guy :(') scores = tuple(SCORE_INITIAL for i in range(2)) random.seed(int(time.time() * 1e5)) recently_is_beaten = [] print('Well, we play a simple dice game! :)') for i in range(NUM_ROUNDS): is_beaten, scores = play_round(scores) print('After round %d the scores are %s' % (i, scores)) if scores[0] <= 0: raise WeBreakup('I feel humiliated. :(') recently_is_beaten.append(is_beaten) if recently_is_beaten[-5:].count(True) >= 5: raise WeBreakup('How dare you beat me 5 times in a streak! :(') if scores[0] < scores[1]: raise WeBreakup('Do you think it is more important to win this game than making me happy? :(') elif scores[1] > scores[0]: raise WeBreakup('You are still too young too simple! :(') else: print(u'I \u2661 U!') response = input() if response == 'Me too! <3': key_f = open('./flag', 'r') print('Flag: %s' % key_f.read().strip()) key_f.close()if __name__ == '__main__': play_game()
确实算是个掷筛子的游戏,向服务器发送“big”或者“small”猜大小。双方各100分,猜对我方加分8分,猜错扣12分,对方反之。猜1000次。如果最后两人的分数一样,则打印flag。一个两人零和的游戏。但是猜对概率是二分之一。而且还有2条限制条件
1.不能连赢5次
2.对方分数不能小于0
有这么多限制,在概率上达到平局的概率基本上是不可能了。虽然可以发送些“aaa”之类的可以保正出错。但是无论如何,我方是必输的。。。╮( ̄▽ ̄)╭
所以只能是另外想办法了。
然后注意到了这个random.seed(int(time.time() * 1e5))这个随机函数是以系统时间来做seed的。相信了解过随机函数的都知道,只要知道了一个随机函数的seed和函数的算法,那么随机函数的值是完全可以预测的。问题就是得到int(time.time() * 1e5)的值了。不过因为网络延时和系统时间的不同,再加上坑爹的1e5次。所以要同步时间是个大问题。
所以先写了这么两段代码
import socketimport timeimport randomlist = []scores = 0a=0str=""s = socket.socket()s.connect(('119.254.101.232',9999))print (s.recv(100))s.send(b'Sure!\n')print (s.recv(100))Seed=int(time.time() * 1e5)i=0right = 0while i<20: s.send(b"big\n") h=s.recv(100) print (h) if h[0] == 67: list = list + [1] scores += 1 else: list = list + [0] i+=1print (v,list)s.close()
第一段代码,用本地的一个time函数获取seed可能的值,然后从服务器上拖了20次猜数字的结果下来。这里我故意在recv之后再调用time。目的是为了让本地的时间数字上大于服务器端的。这样算法比较简单。
把刚才的Seed,和list粘贴到这里。
flag=0x=1while(flag==0): x += 1 random.seed(v-x) print (x) i=0 while(i<20): point = random.randint(1, 6) if point<=3: if list[i] == 1: break else: if list[i] == 0: break i += 1 else: print ("boom",x) flag = 1
这段代码模拟了服务器上的环境,用暴力枚举的方法把seed给爆破了出来。大概是5W左右。。。
坑得的1e5。每次同步修正的数值都不一样,波动都在100以上。在这里卡住了。
后来行为来回的粘贴挺麻烦的,所以我把两段代码给放在一起,然后再得到样本的同时直接跑出修正值来看看。
然后,我为我的智商感到担忧。。。既然可以直接跑出seed的值了。我干啥还要断开连接呢?直接继续跑就可以了(╯‵□′)╯︵┻━┻
然后,就有了下面这段代码。
#!/bin/env python#coding:utf-8import socketimport timeimport randomlist = []right_times = 0a=0str=""s = socket.socket()s.connect(('119.254.101.232',9999))print (s.recv(100))s.send(b'Sure!\n')print (s.recv(100))x=50000v=int(time.time() * 1e5-x)random.seed(v)i=0right = 0while i<20: point = random.randint(1, 6) s.send(b"big\n") h=s.recv(100) print (h) if h[0] == 67: list = list + [1] right_times += 1 else: list = list + [0] i+=1print(v)flag=0x=1while(flag==0): x += 1 random.seed(v-x) print (x) i=0 while(i<20): point = random.randint(1, 6) if point<=3: if list[i] == 1: break else: if list[i] == 0: break i += 1 else: print ("boom",x) flag = 1v -=xrandom.seed(v)i=0while i<20: point = random.randint(1, 6) i+=1i=0k= right_times//4+1while i<230+k+right_times: point = random.randint(1, 6) s.send(b"aaa\n") h=s.recv(100) print (h) i+=1q=0 while right_times<600: if q ==4: point = random.randint(1, 6) s.send(b"aaa\n") h=s.recv(100) print (h) q=0 point = random.randint(1, 6) if point > 3: s.send(b"big\n") else: s.send(b"small\n") h=s.recv(100) print (h) q += 1 right_times +=1s.send(b"Me too! <3\n") h=s.recv(100)print (h)s.close()
总之,思想就是先在线取样本,在本地跑seed,然后总共构造出赢600次,输400次。注意不要半路被踢和random次数始终和服务器保持一致就可以了。最后就是服务器有时间限制,如果超时直接断开连接。所以注意跑seed的时候要稍微估算一下防止超时。
PS:靠着我那刚学1星期的python写出的半吊子代码,就不要吐槽了 ╮( ̄▽ ̄)╭
祝贺协会在这次ctf中取得好成绩。
- ACTF Dice Game Writeup
- ACTF writeup
- ACTF writeup
- SOJ.Dice Game
- Sicily 13907. Dice Game
- CSU1577: Dice Game
- csu 1577: Dice Game
- Game of Dice Gym
- Game of Dice GYM101532E
- HDU 3959 Board Game Dice
- projecteuler No.205 Dice Game
- nyoj 408 Board Game Dice
- Sicily 7966. Another Dice Game
- Gym-100502D Dice Game
- Google最新XSS Game Writeup
- 2011 Alibaba Programming Contest_1009_Board Game Dice
- NYOJ--408题Board Game Dice
- hdu - 3959 Board Game Dice(数学)
- eclipse打不开出现问题
- 常识:数据挖掘最常见的十种方法
- SQL Server 2008 清空删除日志文件(瞬间日志变几M)
- DSP程序跑飞的体会
- DSP BootLoader(zz)
- ACTF Dice Game Writeup
- iOS屏幕截图,裁切图片(制作头像),添加图片水印(Quarz2D)
- 13个小技巧帮你征服Xcode
- 浏览器运行java客户端配置
- Keil提示:missing ‘;’ before ‘xxxxx’,问题解决
- Java设计模式之wrapper
- 3、文件上传
- (译)KVO的内部实现
- 50 Pow(x, n)