萌新带你开车上p站(三)

本文作者:萌新

前情回顾:

萌新带你开车上p站(一)

萌新带你开车上p站(二)

 

0x08


 

题目给的提示是和运算符优先级有关

 1.png

登录后直接看源码

 

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
mistake@pwnable:~$ ls
 
flag  mistake  mistake.c  password
 
mistake@pwnable:~$ cat mistake.c
 
#include <stdio.h>
 
#include <fcntl.h>
 
  
 
#define PW_LEN 10
 
#define XORKEY 1
 
  
 
void xor(char* s, int len){
 
int i;
 
for(i=0; i<len; i++){
 
s[i] ^= XORKEY;
 
}
 
}
 
  
 
int main(int argc, char* argv[]){
 
  
 
  
 
int fd;
 
if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0){
 
printf("can't open password %d\n", fd);
 
return 0;
 
}
 
  
 
printf("do not bruteforce...\n");
 
sleep(time(0)%20);
 
  
 
char pw_buf[PW_LEN+1];
 
int len;
 
if(!(len=read(fd,pw_buf,PW_LEN) > 0)){
 
printf("read error\n");
 
close(fd);
 
return 0;
 
}
 
  
 
char pw_buf2[PW_LEN+1];
 
printf("input password : ");
 
scanf("%10s", pw_buf2);
 
  
 
// xor your input
 
xor(pw_buf2, 10);
 
  
 
if(!strncmp(pw_buf, pw_buf2, PW_LEN)){
 
printf("Password OK\n");
 
system("/bin/cat flag\n");
 
}
 
else{
 
printf("Wrong Password\n");
 
}
 
  
 
close(fd);
 
return 0;
 
}

 

看关键:

main调用的xor函数: 

2.png

将长度给len的字符串与1异或

main中的主要逻辑 

3.jpg

从/home/mistake/password读10个字节数据放到pw_buf,我们手动输入10字节数据放在pw_buf2,如果pw_buf2与1异或的结果如果与pw_buf相等,则打印flag

那么关键就是pw_buf的数据,先直接读password看看 

4.png

没有权限

题目的提示是和运算符优先级有关

我们仔细分析源码,看看问题出在哪里

问题在这里

if(fd=open("/home/mistake/password",O_RDONLY,0400) < 0){

open函数里权限检查是没问题的,O_RDONLY表示以只读方式打开

0400表示文件所有者具有可读取的权限

由于权限通过检查,所以open函数返回值为0

有因为0<0不成立

所有比较结果为0

然后赋值给fd

即fd为0,表示标准输入,也就是说fd现在是我们可控的

结合之前分析,pw_buf也为我们控制

那就很简单了 

5.png

第一次输入10个1,存入pw_buf

第二次输入10个0,存入pw_buf2,与1异或后覆盖pw_buf2,此时buf2的值也为10个1,满足打印flag的逻辑

 

0x09shellshock


 

查看权限 

6.png

可以看到shellshock程序的所属组的权限位上有s,表示sgid,也就是说在执行shellshock时,用户将获得shellshcok所属组的权限,即执行shellshock后将获得root所在用户组的权限,而由flag这一行的权限位可知,该权限可以读取flag

这一点从源码中也可以看出来

7.png

getegid()返回进程执行有效组识别码。在这里getegid()返回的就是root所在用户组的id

setresuid用于设置ruid,euid,seuid,在这里就是统统都设置为进程当前的egid

setresgid用于设置rgid,egid,sgid,这里也是统统设置为进程当前的egid

因为s标志,所以egid实际上是root所在用户组的id

再根据题目提示的shellshock

这是著名的bash破壳漏洞

直接在网上找到poc修改下即可 

8.png

解释一下发生了什么

首先在当前环境下定义了X函数,函数体由{}括起来,然后在函数体外加了一条额外的语句/bin/cat ./flag即打印flag的命令,这条语句会在后面执行./shellshock时被调用,由于执行shellshock时会有root权限,所以自然就有权限来打印flag了

 

想知道怎么操作吗?点击开始实践——破壳漏洞实践http://www.hetianlab.com/expc.do?ec=ECID172.19.105.222014092915250400001

9.jpg

0x10


 

按照要求连接服务器 

0.jpg

这是一个小游戏

大意是一堆货币里有真币假币,两者重量不同,真币10g,假币9g。给你N个硬币,C次机会,让你猜哪一个是假币。需要在30s的时间里才对100次。

这题其实考的是算法。

分治法解决

举个例子。

一共100个硬币,其中1个是假的,先称重1-49,如果结果整除10,则假币在50-100.

第二轮称50-75,如果不整除10,则假币在其中

第三轮称50-62.。。。。

其实就是简单的二分法

编程

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
import time
 
from pwn import *
 
  
 
conn = remote('0', 9007)
 
conn.recv(10000)
 
for _ in range(100)://猜100次
 
    line = conn.recv(1024).decode('UTF-8').strip().split(' ')
 
  print(line)
 
    n = int(line[0].split('=')[1])//读出给的n,c
 
    c = int(line[1].split('=')[1])
 
    left = 0
 
    right = n//共n个硬币
 
  
 
    for _ in range(c)://二分法猜解
 
        guess = ' '.join(str(left) for left in range(left, int((left+right)/2)))
 
        conn.sendline(guess)//给出需要猜测的货币
 
        output = int(conn.recv(1024).decode('UTF-8').strip())//读取返回称重的结果
 
        if (output % 10 == 0)://整除10的情况
 
            left = int((left+right)/2)
 
        else://不整除的情况
 
            right = int((left+right)/ 2)
 
    conn.sendline(str(left))
 
    print(conn.recv(1024).decode('UTF-8'))//打印一轮的结果
 
print(conn.recv(1024).decode('UTF-8'))
 
conn.close()

 

以上一关的shellshock登录服务器,在tmp目录下新建一个python 脚本

按照提示

用pwntools编写的时候,注意remote(‘0’,9007)

执行如下 

11.png

12.jpg

0x11 blackjack 


 

13.jpg

em...源码有点长,直接看关键部分 

14.png

这里会校验我们输入的金额

如果比cash大则会报错,并要求再次输入

不过再次输入的时候不会报错了

考虑到要赚够1000000,而输的几率比较大

我们可以输入-的金额,比如-1000000,只要输了就可以拿到flag

15.jpg

然后选择y就打印出flag了

16.png

posted @   蚁景网安实验室  阅读(981)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示