首页
社区
课程
招聘
[原创]通过汇编“翻译”的PHP脚本爆破签到题
发表于: 2021-11-20 23:20 2482

[原创]通过汇编“翻译”的PHP脚本爆破签到题

2021-11-20 23:20
2482
1
2
3
4
5
6
7
8
工具
OllyDbg
IDA
PHP
 
题目用户名、序列号
用户名 : 01F845C5B7C52E56
序列号 : 653259165 [0x26EFF19D]

先用题目的用户名和序列号执行一次
图片描述

 

关键提示语是Success!,OllyDbg加载程序,搜索字符串“Success!”可以看到程序最后是比较了eax跟一个常数值然后跳转的,不想等的时候跳转到了提示错误的地方。

 

图片描述
那么关键值就是003A144F处的eax值。
图片描述
图片描述
通过在图例的这些位置打断点用题目用户名和序列号调试,摸清大概流程
图片描述
a. 用户名及其长度通过kctf2021.003A1260计算得一个整数
图片描述
b.得到结果0x744E1CC7
图片描述
c. 序列号653259165(0x26EFF19D)与之前的计算结果0x744E1CC7按位异或
图片描述
d. 得到结果0x52A1ED5A
图片描述
e. 经过kctf2021.003A42B3处理转换为了字符串“52A1ED5A”
图片描述
后边就简单了,字符串”52A1ED5A”及其长度8再次传入kctf2021.003A1260,计算结果整数与常量比较CMP EAX,13B88C77

 

以上过程伪代码:

1
2
3
4
5
6
7
8
username, pass
intRet = f003A1260(username, strlen(username))
intRet2 = intRet ^ intval(pass)
str = hex2str(intRet2)
intRet3 = f003A1260(str, strlen(str))
if (intRet3 == 13B88C77) {
    "Success!"
}

可以看出函数f003A1260为关键,解析来我们看一下kctf2021.003A1260

 

图片描述

 

执行了1次以上过程

 

图片描述
后续有7次执行过程,但是逻辑都相同,总结为执行了7次以上过程
图片描述
最终计算值放到一个数组,然后比较计数器与0x100,如果小于则跳回loc_401275重复操作。

 

以上过程我们根据阅读的注释,翻译为PHP脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
$seed = [];
for ($ecx=0; $ecx < 0x100; $ecx++) {
 
    $v = $ecx;
    $v = $v >> 1;
 
    if (! lastNot1($ecx)) {
        $v = xor0EDB88320($v);// $v ^ 0x0EDB88320;
    }
 
    for ($i=0; $i < 7; $i++) {
        if (!lastNot1($v)) {
            $v = $v >> 1;
            $v = xor0EDB88320($v);// $v ^ 0x0EDB88320;
        } else {
            $v = $v >> 1;
        }
    }
 
    $seed[] = $v;
}

图片描述
初始化ecx,遍历传入的字符串,检测长度,字符串逐字符计算。

 

图片描述
取反,返回。可以看出其中计算数组的部分没有参数参与,每次都是同样的值,所以我们抽出这部分。整个函数最终封装为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function f003A1260($str) {
    global $seed; // 公共数组seed
 
    $ecx = 0x100; // 计算arr便利完就是0x100
    $ecx = or32($ecx, 0x0FFFFFFFF);
 
    $end = strlen($str);
    for ($i=0; $i < $end; $i++) {
        $c = $str[$i];
        $eax = ord($c);
        // var_dump($eax);
        $eax = xor32($eax, $ecx);
 
        $ecx = shr8($ecx);
 
        $eax = low8($eax);
 
        $ecx = xor32($ecx, $seed[$eax]);
    }
 
    $ret = ~$ecx;
    $b = decbin($ret);
    $b = substr($b, -32);
    $b = bindec($b);
 
    return $b;
}

结合上述伪代码,我们做一个爆破脚本s1.php,存入~/bin/s1.php,通过php ~/bin/s1 test来测试题目中的用户名和序列号,通过以下三组来通过猜测的数字区间爆破。

1
2
3
php ~/bin/s1.php 0
php ~/bin/s1.php 1
php ~/bin/s1.php 2

文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
<?php
 
// link : https://ctf.pediy.com/game-season_fight-180.htm
 
$seed = [];
for ($ecx=0; $ecx < 0x100; $ecx++) {
 
    $v = $ecx;
    $v = $v >> 1;
 
    if (! lastNot1($ecx)) {
        $v = xor0EDB88320($v);// $v ^ 0x0EDB88320;
    }
 
    for ($i=0; $i < 7; $i++) {
        if (!lastNot1($v)) {
            $v = $v >> 1;
            $v = xor0EDB88320($v);// $v ^ 0x0EDB88320;
        } else {
            $v = $v >> 1;
        }
    }
 
    $seed[] = $v;
}
 
function f003A1260($str) {
    global $seed; // 公共数组seed
 
    $ecx = 0x100; // 计算arr便利完就是0x100
    $ecx = or32($ecx, 0x0FFFFFFFF);
 
    $end = strlen($str);
    for ($i=0; $i < $end; $i++) {
        $c = $str[$i];
        $eax = ord($c);
        // var_dump($eax);
        $eax = xor32($eax, $ecx);
 
        $ecx = shr8($ecx);
 
        $eax = low8($eax);
 
        $ecx = xor32($ecx, $seed[$eax]);
    }
 
    $ret = ~$ecx;
    $b = decbin($ret);
    $b = substr($b, -32);
    $b = bindec($b);
 
    return $b;
}
 
 
function reschk($pass, $b) {
    $pass = decbin(intval($pass));
    $pass = substr($pass, -32);
    $pass = bindec($pass);
 
    $cc = xor32($pass, $b); // 52A1ED5A
    $hex = dechex($cc);
    $len = 8;
 
    $reschk = f003A1260($hex);
    if ($reschk == 330861687) {
        echo '正确的密钥' . PHP_EOL;
        return true;
    }
 
    return false;
}
 
 
function shr8($v) {
    $v = $v >> 8;
    $b = decbin($v);
    $b = substr($b, -32);
    return bindec($b);
}
 
function or32($a, $b) {
    $c = $a | $b;
    $b = decbin($c);
    $b = substr($b, -32);
    return bindec($b);
}
 
function xor32($a, $b) {
    $c = $a ^ $b;
    $b = decbin($c);
    $b = substr($b, -32);
    return bindec($b);
}
 
function xor8($a, $b) {
    $c = $a ^ $b;
    $b = decbin($c);
    $b = substr($b, -8);
    return bindec($b);
}
 
function lastNot1($ch) {
    $b = decbin($ch);
    $bin = substr($b, -1);
    return !($bin == '1');
}
 
function xor0EDB88320($v) {
    return xor32($v, 0x0EDB88320);
}
 
function low8($ch) {
    $b = decbin($ch);
    $bin = substr($b, -8);
    $h = bindec($bin);
    return $h;
}
 
function test() {
    $str = '01F845C5B7C52E56';
    $b = f003A1260($str);
    if ($b == 1951276231) {
        echo '正确';   
    } else {
        echo '错误';
    }
 
    $pass = '653259165';
 
    $r = reschk($pass, $b);
    if ($r) {
        echo 'yes' . PHP_EOL;
    }
}
 
if (isset($argv[1]) && $argv[1] == 'test') {
    test();exit;
}
 
$username = 'KCTF';
$b = f003A1260($username);
 
$arr = [
    [153259165, 353259165], //最终这个区间跑出了正确值 205824534
    [353259165, 430861687],
    [430861687, 653259165],
];
$s = isset($argv[1]) ? intval($argv[1]) : 0;
$start = $arr[$s][0];
$end = $arr[$s][1];
for ($i=$start; $i < $end; $i++) {
    if ($i == $start + ceil(($end - $start)/2)) {
        echo '一半了' . PHP_EOL;
    }
 
    $r = reschk($i, $b);
    if ($r) {
        echo '最终' . PHP_EOL;
        var_dump($i);exit;
    }
}
echo '没有结果' . PHP_EOL;
 
?>

最终第2组爆得一个结果:
图片描述


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//