<?php
require_once('config.php');
header('Content-Type: application/json');
function response($resp){ #定义了一个函数response对变量resp进行JSON加密
die(json_encode($resp));
}
function response_error($msg){ #定义了一个函数response_error对变量msg出错时调用
$result = ['status'=>'error'];
$result['msg'] = $msg;
response($result);
}
function require_keys($req, $keys){ #定义了一个函数require_keys ???
foreach ($keys as $key) {
if(!array_key_exists($key, $req)){
response_error('invalid request');
}
}
}
function require_registered(){ #没有定义名字和钱数要重新注册
if(!isset($_SESSION['name']) || !isset($_SESSION['money'])){
response_error('register first');
}
}
function require_min_money($min_money){ 规定了钱数不能小于0
if(!isset($_SESSION['money'])){
response_error('register first');
}
$money = $_SESSION['money'];
if($money < 0){
$_SESSION = array();
session_destroy();
response_error('invalid negative money');
}
if($money < $min_money){
response_error('you don\' have enough money');
}
}
if($_SERVER["REQUEST_METHOD"] != 'POST' || !isset($_SERVER["CONTENT_TYPE"]) || $_SERVER["CONTENT_TYPE"] != 'application/json'){
response_error('please post json data');
} #要求POST方式上传,application/json
$data = json_decode(file_get_contents('php://input'), true); 上传的数据会经过JSON解码变成DATA读取的数据
if(json_last_error() != JSON_ERROR_NONE){
response_error('invalid json');
}
require_keys($data, ['action']);
// my boss told me to use cryptographically secure algorithm
function random_num(){ #random的函数大多数不用管
do {
$byte = openssl_random_pseudo_bytes(10, $cstrong);
$num = ord($byte);
} while ($num >= 250);
if(!$cstrong){
response_error('server need be checked, tell admin');
}
$num /= 25;
return strval(floor($num));
}
function random_win_nums(){
$result = '';
for($i=0; $i<7; $i++){
$result .= random_num();
}
return $result;
}
function buy($req){
require_registered(); #调用了刚刚的函数
require_min_money(2);
$money = $_SESSION['money'];
$numbers = $req['numbers'];
$win_numbers = random_win_nums();
$same_count = 0;
for($i=0; $i<7; $i++){ #如果每个值都等于随机产生的胜利数字,相同的个数计数+1
if($numbers[$i] == $win_numbers[$i]){
$same_count++;
}
}
switch ($same_count) {
case 2:
$prize = 5;
break;
case 3:
$prize = 20;
break;
case 4:
$prize = 300;
break;
case 5:
$prize = 1800;
break;
case 6:
$prize = 200000;
break;
case 7:
$prize = 5000000; #我们要达到相同的是7个的情况
break;
default:
$prize = 0;
break;
}
$money += $prize - 2; #钱数就要减少2元了
$_SESSION['money'] = $money;
response(['status'=>'ok','numbers'=>$numbers, 'win_numbers'=>$win_numbers, 'money'=>$money, 'prize'=>$prize]);
}
function flag($req){
global $flag;
global $flag_price;
require_registered();
$money = $_SESSION['money'];
if($money < $flag_price){
response_error('you don\' have enough money');
} else {
$money -= $flag_price;
$_SESSION['money'] = $money;
$msg = 'Here is your flag: ' . $flag;
response(['status'=>'ok','msg'=>$msg, 'money'=>$money]);
}
}
function register($req){ 这是主函数,
$name = $req['name'];
$_SESSION['name'] = $name;
$_SESSION['money'] = 20;
response(['status'=>'ok']);
}
switch ($data['action']) {
case 'buy': 买
require_keys($data, ['numbers']);
buy($data);
break;
case 'flag': 显示答案
flag($data);
break;
case 'register': 注册
require_keys($data, ['name']);
register($data);
break;
default:
response_error('invalid request');
break;
}
主函数在最下面,上面调用了很多函数,有些比如说random 的,erro的就不用去看了,主函数分析来,一个是买,一个是显示flag了,显示的前提是你要有钱(此处对钱进行了一个比较),最后是注册,没什么好说,然后报错,不用看,那重点就是钱了,哪里能得到钱呢,就是在买这个case里面,能得到大钱的前提是你输入的数字,和随机7位数字相同。
这怎么可能???
但是通过我们一行行分析代码可以发现有一个json加密的过程,
var p = {“name”:“张三”,“age”:“23”,“gender”:“男”};
这种叫jason
那分析来我们上次的数据可能就是
{“money”:“2”,“number”:“1234567”};
大概是这么个构造,
而比较的时候是==
那么json才有布尔的方式进行判断
{“money”:“2”,“number”:“true true true true true true true”};
我们抓包来实验一下
抓到啦,瞧和我们分析 的差不多
最终定位到这里,利用php的弱比较,true和int比较都是成立的。
所以将刚刚的包改成[true,true,true,true,true,true,true]。
我卡了一个小时 因为我的火狐浏览器没有开cookie 的权限,每次度无法注册成功
这个时候,把拦截包功能选择off,网页就自动跳转网页了显示你得到了多少钱,
去买那个flag就好了呀~