atoi

64ida打开,main函数f5

avatar

只有一个输入,只要满足判断条件即可提权

avatar

而要满足判断条件很简单(atoi函数可以搜一下),输入501#501#即可(其中#号可以换成其他字符)

boundary

ida32打开,分析结果如下:

avatar

很简单,撞墙之后会提示try Q;然后再次连接,生成地图后输入q即可提权。(英文看不懂的自己翻译)

白给的random

源码

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
#include<stdio.h>
#include<stdlib.h>

int main(){
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
int j=0;
puts("Please enter your seed.");
puts("Everything that happens later is related to the seed you entered");
int seed;
printf("seed:");
scanf("%d",&seed);
srand(seed);
int num[3];
int q[3];
num[0] = rand() % 100;
num[1] = rand() % 100;
num[2] = rand() % 100;

for(;j<=2;j++){
printf("Please enter your lucky number %d: ",j+1);
scanf("%d",&q[j]);
}
for(j=0;j<=2;j++){
if(num[j] == q[j]){
if(j == 0)
printf("Your first lucky number is the same as mine.Continue\n");
else if(j == 1)
printf("Your second lucky number is the same as mine.Continue\n");
else
printf("Your third lucky number is the same as mine.Congratulations!.");
}
else{
if(j==0){
printf("Your first lucky number is %d\n",q[j]);
printf("But my first lucky number is %d\n",num[j]);
printf("I can't give you system");
exit(0);
}
else if(j==1){
printf("Your second lucky number is %d\n",q[j]);
printf("But my second lucky number is %d\n",num[j]);
printf("I can't give you system");
exit(0);
}
else{
printf("Your third lucky number is %d\n",q[j]);
printf("But my third lucky number is %d\n",num[j]);
printf("I can't give you system");
exit(0);
}
}
}
system("/bin/sh");
return 0;
}

考察的知识点是伪随机数,只要srand设置的种子不变值也不变
写一个random.c文件

1
2
3
4
5
6
7
8
#include<stdio.h>
#include<stdlib.h>
int main(){
srand(0);
for(int i = 0; i<= 2; i++){
printf("%d\n",rand()%100);
}
}

生成的三个随机数83、86、77,依次输入seed:0,83、86、77就能getshell

白给的真random

源码

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
#include<iostream>
#include<string>
#include<stdlib.h>
#include<algorithm>
#include<time.h>

using namespace std;
void sub115a(string a,char *b);
void menu();

const string tmp = "100011000000110010101100100011000000110010101100100011000000110010101100100011000000110010101100110011101001111011001110";
const string tmp1 = "orange";

int main(){

menu();

string s;

string s1;
char ss[200]= {'\0'};
string sd;

int num;
srand(time(NULL));
int random = rand() % 16;

cout << "111001100111011010010110010011100010111011001110: ";
cin >> s;

if(s.compare(tmp1)){
cout << "Error" << endl;
exit(0);
}

cout << "You get the first key!" <<endl;

cout << "111001100111011010010110010011100010111011001110: ";
cin >> s1;
sub115a(s1,ss);

sd = ss;
reverse(sd.begin(),sd.end());

if(sd.compare(tmp)){
cout << "Error" << endl;
exit(0);
}

cout << "You get the second key!!" << endl;
cout << "A strange word is engraved on the key for blasting " << endl;
cout << "001011100111011010010110: ";

cin >> num;

if(num != random ){
cout << "Error" << endl;
exit(0);

}

cout << "You get the third key!!!" << endl;
system("/bin/sh");
}

void menu(){
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
cout << "Welcome to my mystery shop." << endl;
cout << "As long as you can pick three keys, I will give you the system" << endl;
cout << "Try your best to pick these three keys. " << endl;
cout <<"Now start your game" << endl;

}

void sub115a(string a,char *b){
int len = a.size();
int idx = 0;
for( int i = 0; i < len; i++){
b[idx] = 48 + ((a[i]>>7)&1);
b[idx + 1] = 48 + ((a[i]>>6)&1);
b[idx + 2] = 48 + ((a[i]>>5)&1);
b[idx + 3] = 48 + ((a[i]>>4)&1);
b[idx + 4] = 48 + ((a[i]>>3)&1);
b[idx + 5] = 48 + ((a[i]>>2)&1);
b[idx + 6] = 48 + ((a[i]>>1)&1);
b[idx + 7] = 48 + ((a[i])&1);
idx += 8;
}
}

ida中反编译后的源码

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
__int64 v4; // rax
__int64 v5; // rax
__int64 v6; // rbx
__int64 v7; // rax
__int64 v8; // rax
__int64 v9; // rax
__int64 v10; // rax
__int64 v11; // rax
__int64 v12; // rax
int v14; // [rsp+Ch] [rbp-174h] BYREF
char v15[32]; // [rsp+10h] [rbp-170h] BYREF
__int64 v16[26]; // [rsp+30h] [rbp-150h] BYREF
char v17[32]; // [rsp+100h] [rbp-80h] BYREF
char v18[32]; // [rsp+120h] [rbp-60h] BYREF
char v19[44]; // [rsp+140h] [rbp-40h] BYREF
int v20; // [rsp+16Ch] [rbp-14h]

menu();
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v18, argv);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v17, argv);
v16[0] = 0LL;
v16[1] = 0LL;
v16[2] = 0LL;
v16[3] = 0LL;
v16[4] = 0LL;
v16[5] = 0LL;
v16[6] = 0LL;
v16[7] = 0LL;
v16[8] = 0LL;
v16[9] = 0LL;
v16[10] = 0LL;
v16[11] = 0LL;
v16[12] = 0LL;
v16[13] = 0LL;
v16[14] = 0LL;
v16[15] = 0LL;
v16[16] = 0LL;
v16[17] = 0LL;
v16[18] = 0LL;
v16[19] = 0LL;
v16[20] = 0LL;
v16[21] = 0LL;
v16[22] = 0LL;
v16[23] = 0LL;
v16[24] = 0LL;
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v15, argv);
v3 = time(0LL);
srand(v3);
v20 = rand() % 16;
std::operator<<<std::char_traits<char>>(&std::cout, "111001100111011010010110010011100010111011001110: ");
std::operator>><char>(&std::cin, v18);
if ( (unsigned int)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::compare(v18, &tmp1) )//这里为第一个判断,对应第一次输入
{
v4 = std::operator<<<std::char_traits<char>>(&std::cout, "Error");
std::ostream::operator<<(v4, &std::endl<char,std::char_traits<char>>);
exit(0);
}
v5 = std::operator<<<std::char_traits<char>>(&std::cout, "You get the first key!");
std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
std::operator<<<std::char_traits<char>>(&std::cout, "111001100111011010010110010011100010111011001110: ");
std::operator>><char>(&std::cin, v17);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v19, v17);
sub115a(v19, v16);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v19);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator=(v15, v16);
v6 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::end(v15);
v7 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::begin(v15);
std::reverse<__gnu_cxx::__normal_iterator<char *,std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>>>(
v7,
v6);
if ( (unsigned int)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::compare(v15, &tmp) )//这里为第二个判断
{
v8 = std::operator<<<std::char_traits<char>>(&std::cout, "Error");
std::ostream::operator<<(v8, &std::endl<char,std::char_traits<char>>);
exit(0);
}
v9 = std::operator<<<std::char_traits<char>>(&std::cout, "You get the second key!!");
std::ostream::operator<<(v9, &std::endl<char,std::char_traits<char>>);
v10 = std::operator<<<std::char_traits<char>>(&std::cout, "A strange word is engraved on the key for blasting ");
std::ostream::operator<<(v10, &std::endl<char,std::char_traits<char>>);
std::operator<<<std::char_traits<char>>(&std::cout, "001011100111011010010110: ");
std::istream::operator>>(&std::cin, &v14);
if ( v20 != v14 )//这个为第三个判断
{
v11 = std::operator<<<std::char_traits<char>>(&std::cout, "Error");
std::ostream::operator<<(v11, &std::endl<char,std::char_traits<char>>);
exit(0);
}
v12 = std::operator<<<std::char_traits<char>>(&std::cout, "You get the third key!!!");
std::ostream::operator<<(v12, &std::endl<char,std::char_traits<char>>);
system("/bin/sh");
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v15);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v17);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v18);
return 0;
}

第一个判断为v18和tmp1的比较,tmp1地址为0x4043E0
gdb查看tmp1如下

1
2
3
4
5
$ gdb ./
pwndbg> x/1gx 0x4043E0
0x4043e0 <_ZL4tmp1>: 0x00000000004043f0
pwndbg> x/1s 0x00000000004043f0
0x4043f0 <_ZL4tmp1+16>: "orange"

可以看到tmp1最终指向orange,第一次输入即为orange
第二个判断为v5与tmp的比较,tmp地址为0x4043C0
gdb查看tmp如下

1
2
3
4
pwndbg> x/1gx 0x4043C0
0x4043c0 <_ZL3tmp>: 0x0000000000416eb0
pwndbg> x/1s 0x416eb0
0x416eb0: "100011000000110010101100100011000000110010101100100011000000110010101100100011000000110010101100110011101001111011001110"

可以看到tmp1最后指向一串2进制字符,将2进制字符倒过来转ascii即是输入内容”sys501501501501”
第二个判断输入sys501501501501就可以绕过了(正好对应题目被倒过来的描述内容),当然没想到将2进制反转
再转字符串也还有别的方法,分析清楚程序逻辑也是一样的
sub115a这个函数的作用是将字符串转2进制, std::reverse这个是c++的库函数,将字符串翻转
最后一个判断是输入一个数字与一个0-15的随机数比较(真随机),看exp那个while(1)就明白了
exp如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *

while(1):
p = remote("192.168.43.251",10000)
p.recvuntil("game\n")
p.sendlineafter(": ","orange")
p.sendlineafter(": ","sys501501501501")
p.sendlineafter(": ","10")
a = p.recv()

if(b"key" in a):
p.interactive()
else:
p.close()