攻防世界(XCTF)逆向部分write up

Posted -qing-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了攻防世界(XCTF)逆向部分write up相关的知识,希望对你有一定的参考价值。

晚上做几个简单的ctf逆向睡的更好

 

 

 

 

 

logmein

elf文件 ida看看main函数伪代码

void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)

  size_t v3; // rsi
  int i; // [rsp+3Ch] [rbp-54h]
  char s[36]; // [rsp+40h] [rbp-50h]
  int v6; // [rsp+64h] [rbp-2Ch]
  __int64 v7; // [rsp+68h] [rbp-28h]
  char v8[8]; // [rsp+70h] [rbp-20h]
  int v9; // [rsp+8Ch] [rbp-4h]

  v9 = 0;
  strcpy(v8, ":\\"AL_RT^L*.?+6/46");
  v7 = 28537194573619560LL;
  v6 = 7;
  printf("Welcome to the RC3 secure password guesser.\\n", a2, a3);
  printf("To continue, you must enter the correct password.\\n");
  printf("Enter your guess: ");
  __isoc99_scanf("%32s", s);
  v3 = strlen(s);
  if ( v3 < strlen(v8) )
    sub_4007C0(v8);
  for ( i = 0; i < strlen(s); ++i )
  
    if ( i >= strlen(v8) )
      ((void (*)(void))sub_4007C0)();
    if ( s[i] != (char)(*((_BYTE *)&v7 + i % v6) ^ v8[i]) )
      ((void (*)(void))sub_4007C0)();
  
  sub_4007F0();

 

这里要看懂他的算法:

 

看到19行sacnf接收输入  然后v3为输入的长度v3 < strlen(v8)调用sub_4007C0函数传入v8    

技术图片

 

 

sub_4007C0:

技术图片

 

 

接着看sub_4007F0

技术图片

 

 

函数看完 26行左右就是flag的行 

 

输入的字符要等于  经过处理的v7和v8的异或。

v7 int64  v7要转换为16进制然后在转换为字符串,而且字符是小端序,所以把得到的字符翻转然后和v8的每一位进行异或。

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BYTE unsigned char

int main(int argc, char* argv[]) 
    unsigned int i;
    char v8[18] = ":\\"AL_RT^L*.?+6/46";
    __int64 v7 = 28537194573619560;
    int v6 = 7;

    char s[18] = "";
    for (i = 0; i < strlen(v8); ++i) 
        s[i] = (char)(*((BYTE*)&v7 + i % v6)^v8[i]);
    

    printf("%s\\n", s);

    system("PAUSE");
    return 0;

 

技术图片

 

 

 

 

 

 

re1 

技术图片

 

 

F5看看伪代码

技术图片

 

将用户输入的flag存入v9,然后将v9和v5比较,如果值相同输出aFlag
既然需要比较flag,那正确的flag应该已经作为一个常量保存在程序内部,可以尝试直接查找flag

 

ida查看程序的字符串  有时候ida会把字符串当数据 所以这里直接查看hex view

技术图片

 

 

 

 

 

 

 

 

 

 

 

game

 

看看有没得壳

 

技术图片

 

 

打开程序,是一个小游戏,直接输入12345678就能直接拿到flag

技术图片

 

 

在函数中搜索main

技术图片

 

 

 

看main_0()

    void __cdecl main_0()
    
      signed int i; // [esp+DCh] [ebp-20h]
      int v1; // [esp+F4h] [ebp-8h]
    
      sub_13FA7BE(&unk_14AB110);
      sub_13FA7BE(&unk_14AB158);
      sub_13FA7BE(&unk_14AB1A0);
      sub_13FA7BE(&unk_14AB1E8);
      sub_13FA7BE(&unk_14AB230);
      sub_13FA7BE(&unk_14AB278);
      sub_13FA7BE(&unk_14AB2C0);
      sub_13FA7BE(&unk_14AB308);
      sub_13FA7BE(&unk_14AAFD0);
      sub_13FA7BE("|              by 0x61                                 |\\n");
      sub_13FA7BE("|                                                      |\\n");
      sub_13FA7BE("|------------------------------------------------------|\\n");
      sub_13FA7BE(
        "Play a game\\n"
        "The n is the serial number of the lamp,and m is the state of the lamp\\n"
        "If m of the Nth lamp is 1,it‘s on ,if not it‘s off\\n"
        "At first all the lights were closed\\n");
      sub_13FA7BE("Now you can input n to change its state\\n");
      sub_13FA7BE(
        "But you should pay attention to one thing,if you change the state of the Nth lamp,the state of (N-1)th and (N+1)th w"
        "ill be changed too\\n");
      sub_13FA7BE("When all lamps are on,flag will appear\\n");
      sub_13FA7BE("Now,input n \\n");
      while ( 1 )
      
        while ( 1 )
        
          sub_13FA7BE("input n,n(1-8)\\n");
          sub_13F9418();
          sub_13FA7BE("n=");
          sub_13F96D4("%d", &v1);
          sub_13FA7BE("\\n");
          if ( v1 >= 0 && v1 <= 8 )
            break;
          sub_13FA7BE("sorry,n error,try again\\n");
        
        if ( v1 )
        
          sub_13F76D6(v1 - 1);
        
        else
        
          for ( i = 0; i < 8; ++i )
          
            if ( (unsigned int)i >= 9 )
              j____report_rangecheckfailure();
            byte_14D2E28[i] = 0;
          
        
        j__system("CLS");
        sub_13F8054();
        if ( byte_14D2E28[0] == 1
          && byte_14D2E28[1] == 1
          && byte_14D2E28[2] == 1
          && byte_14D2E28[3] == 1
          && byte_14D2E28[4] == 1
          && byte_14D2E28[5] == 1
          && byte_14D2E28[6] == 1
          && byte_14D2E28[7] == 1 )
        
          sub_13F7AB4();
        
      
    

 

发现最后跳转的sub_13F7AB4()的函数可能有东西 跟进

int sub_457AB4(void)

  return sub_45E940();

再跟进sub_45E940()

    int sub_13FE940()
    
      signed int i; // [esp+D0h] [ebp-94h]
      char v2; // [esp+DCh] [ebp-88h]
      char v3; // [esp+DDh] [ebp-87h]
      char v4; // [esp+DEh] [ebp-86h]
      char v5; // [esp+DFh] [ebp-85h]
      char v6; // [esp+E0h] [ebp-84h]
      char v7; // [esp+E1h] [ebp-83h]
      char v8; // [esp+E2h] [ebp-82h]
      char v9; // [esp+E3h] [ebp-81h]
      char v10; // [esp+E4h] [ebp-80h]
      char v11; // [esp+E5h] [ebp-7Fh]
      char v12; // [esp+E6h] [ebp-7Eh]
      char v13; // [esp+E7h] [ebp-7Dh]
      char v14; // [esp+E8h] [ebp-7Ch]
      char v15; // [esp+E9h] [ebp-7Bh]
      char v16; // [esp+EAh] [ebp-7Ah]
      char v17; // [esp+EBh] [ebp-79h]
      char v18; // [esp+ECh] [ebp-78h]
      char v19; // [esp+EDh] [ebp-77h]
      char v20; // [esp+EEh] [ebp-76h]
      char v21; // [esp+EFh] [ebp-75h]
      char v22; // [esp+F0h] [ebp-74h]
      char v23; // [esp+F1h] [ebp-73h]
      char v24; // [esp+F2h] [ebp-72h]
      char v25; // [esp+F3h] [ebp-71h]
      char v26; // [esp+F4h] [ebp-70h]
      char v27; // [esp+F5h] [ebp-6Fh]
      char v28; // [esp+F6h] [ebp-6Eh]
      char v29; // [esp+F7h] [ebp-6Dh]
      char v30; // [esp+F8h] [ebp-6Ch]
      char v31; // [esp+F9h] [ebp-6Bh]
      char v32; // [esp+FAh] [ebp-6Ah]
      char v33; // [esp+FBh] [ebp-69h]
      char v34; // [esp+FCh] [ebp-68h]
      char v35; // [esp+FDh] [ebp-67h]
      char v36; // [esp+FEh] [ebp-66h]
      char v37; // [esp+FFh] [ebp-65h]
      char v38; // [esp+100h] [ebp-64h]
      char v39; // [esp+101h] [ebp-63h]
      char v40; // [esp+102h] [ebp-62h]
      char v41; // [esp+103h] [ebp-61h]
      char v42; // [esp+104h] [ebp-60h]
      char v43; // [esp+105h] [ebp-5Fh]
      char v44; // [esp+106h] [ebp-5Eh]
      char v45; // [esp+107h] [ebp-5Dh]
      char v46; // [esp+108h] [ebp-5Ch]
      char v47; // [esp+109h] [ebp-5Bh]
      char v48; // [esp+10Ah] [ebp-5Ah]
      char v49; // [esp+10Bh] [ebp-59h]
      char v50; // [esp+10Ch] [ebp-58h]
      char v51; // [esp+10Dh] [ebp-57h]
      char v52; // [esp+10Eh] [ebp-56h]
      char v53; // [esp+10Fh] [ebp-55h]
      char v54; // [esp+110h] [ebp-54h]
      char v55; // [esp+111h] [ebp-53h]
      char v56; // [esp+112h] [ebp-52h]
      char v57; // [esp+113h] [ebp-51h]
      char v58; // [esp+114h] [ebp-50h]
      char v59; // [esp+120h] [ebp-44h]
      char v60; // [esp+121h] [ebp-43h]
      char v61; // [esp+122h] [ebp-42h]
      char v62; // [esp+123h] [ebp-41h]
      char v63; // [esp+124h] [ebp-40h]
      char v64; // [esp+125h] [ebp-3Fh]
      char v65; // [esp+126h] [ebp-3Eh]
      char v66; // [esp+127h] [ebp-3Dh]
      char v67; // [esp+128h] [ebp-3Ch]
      char v68; // [esp+129h] [ebp-3Bh]
      char v69; // [esp+12Ah] [ebp-3Ah]
      char v70; // [esp+12Bh] [ebp-39h]
      char v71; // [esp+12Ch] [ebp-38h]
      char v72; // [esp+12Dh] [ebp-37h]
      char v73; // [esp+12Eh] [ebp-36h]
      char v74; // [esp+12Fh] [ebp-35h]
      char v75; // [esp+130h] [ebp-34h]
      char v76; // [esp+131h] [ebp-33h]
      char v77; // [esp+132h] [ebp-32h]
      char v78; // [esp+133h] [ebp-31h]
      char v79; // [esp+134h] [ebp-30h]
      char v80; // [esp+135h] [ebp-2Fh]
      char v81; // [esp+136h] [ebp-2Eh]
      char v82; // [esp+137h] [ebp-2Dh]
      char v83; // [esp+138h] [ebp-2Ch]
      char v84; // [esp+139h] [ebp-2Bh]
      char v85; // [esp+13Ah] [ebp-2Ah]
      char v86; // [esp+13Bh] [ebp-29h]
      char v87; // [esp+13Ch] [ebp-28h]
      char v88; // [esp+13Dh] [ebp-27h]
      char v89; // [esp+13Eh] [ebp-26h]
      char v90; // [esp+13Fh] [ebp-25h]
      char v91; // [esp+140h] [ebp-24h]
      char v92; // [esp+141h] [ebp-23h]
      char v93; // [esp+142h] [ebp-22h]
      char v94; // [esp+143h] [ebp-21h]
      char v95; // [esp+144h] [ebp-20h]
      char v96; // [esp+145h] [ebp-1Fh]
      char v97; // [esp+146h] [ebp-1Eh]
      char v98; // [esp+147h] [ebp-1Dh]
      char v99; // [esp+148h] [ebp-1Ch]
      char v100; // [esp+149h] [ebp-1Bh]
      char v101; // [esp+14Ah] [ebp-1Ah]
      char v102; // [esp+14Bh] [ebp-19h]
      char v103; // [esp+14Ch] [ebp-18h]
      char v104; // [esp+14Dh] [ebp-17h]
      char v105; // [esp+14Eh] [ebp-16h]
      char v106; // [esp+14Fh] [ebp-15h]
      char v107; // [esp+150h] [ebp-14h]
      char v108; // [esp+151h] [ebp-13h]
      char v109; // [esp+152h] [ebp-12h]
      char v110; // [esp+153h] [ebp-11h]
      char v111; // [esp+154h] [ebp-10h]
      char v112; // [esp+155h] [ebp-Fh]
      char v113; // [esp+156h] [ebp-Eh]
      char v114; // [esp+157h] [ebp-Dh]
      char v115; // [esp+158h] [ebp-Ch]
    
      sub_13FA7BE("done!!! the flag is ");
      v59 = 18;
      v60 = 64;
      v61 = 98;
      v62 = 5;
      v63 = 2;
      v64 = 4;
      v65 = 6;
      v66 = 3;
      v67 = 6;
      v68 = 48;
      v69 = 49;
      v70 = 65;
      v71 = 32;
      v72 = 12;
      v73 = 48;
      v74 = 65;
      v75 = 31;
      v76 = 78;
      v77 = 62;
      v78 = 32;
      v79 = 49;
      v80 = 32;
      v81 = 1;
      v82 = 57;
      v83 = 96;
      v84 = 3;
      v85 = 21;
      v86 = 9;
      v87 = 4;
      v88 = 62;
      v89 = 3;
      v90 = 5;
      v91 = 4;
      v92 = 1;
      v93 = 2;
      v94 = 3;
      v95 = 44;
      v96 = 65;
      v97 = 78;
      v98 = 32;
      v99 = 16;
      v100 = 97;
      v101 = 54;
      v102 = 16;
      v103 = 44;
      v104 = 52;
      v105 = 32;
      v106 = 64;
      v107 = 89;
      v108 = 45;
      v109 = 32;
      v110 = 65;
      v111 = 15;
      v112 = 34;
      v113 = 18;
      v114 = 16;
      v115 = 0;
      v2 = 123;
      v3 = 32;
      v4 = 18;
      v5 = 98;
      v6 = 119;
      v7 = 108;
      v8 = 65;
      v9 = 41;
      v10 = 124;
      v11 = 80;
      v12 = 125;
      v13 = 38;
      v14 = 124;
      v15 = 111;
      v16 = 74;
      v17 = 49;
      v18 = 83;
      v19 = 108;
      v20 = 94;
      v21 = 108;
      v22 = 84;
      v23 = 6;
      v24 = 96;
      v25 = 83;
      v26 = 44;
      v27 = 121;
      v28 = 104;
      v29 = 110;
      v30 = 32;
      v31 = 95;
      v32 = 117;
      v33 = 101;
      v34 = 99;
      v35 = 123;
      v36 = 127;
      v37 = 119;
      v38 = 96;
      v39 = 48;
      v40 = 107;
      v41 = 71;
      v42 = 92;
      v43 = 29;
      v44 = 81;
      v45 = 107;
      v46 = 90;
      v47 = 85;
      v48 = 64;
      v49 = 12;
      v50 = 43;
      v51 = 76;
      v52 = 86;
      v53 = 13;
      v54 = 114;
      v55 = 1;
      v56 = 117;
      v57 = 126;
      v58 = 0;
      for ( i = 0; i < 56; ++i )
      
        *(&v2 + i) ^= *(&v59 + i);
        *(&v2 + i) ^= 0x13u;
      
      return sub_13FA7BE("%s\\n");
    

 

这应该就是打印flag的函数了  这个两个57字节的变量进行循环打印异或 写个脚本 有点麻烦静态分析出来的

    a=[18,64,98,5,2,4,6,3,6,48,49,65,32,12,48,65,31,78,62,32,49,32,
       1,57,96,3,21,9,4,62,3,5,4,1,2,3,44,65,78,32,16,97,54,16,44,
       52,32,64,89,45,32,65,15,34,18,16,0]
    b=[123,32,18,98,119,108,65,41,124,80,125,38,124,111,74,49,
       83,108,94,108,84,6,96,83,44,121,104,110,32,95,117,101,99,
       123,127,119,96,48,107,71,92,29,81,107,90,85,64,12,43,76,86,
       13,114,1,117,126,0]
    i=0
    c=‘‘
    while (i<56):
        a[i]^=b[i]
        a[i]^=19
        c=c+chr(a[i])
        i=i+1
    print (c)

 

 

 

Hello, CTF

打开 发现是输入然后比对 

技术图片

 

 

看看main函数

技术图片

 

 strcpy把那串字符串复制给v13地址

第36~39行代码是判断输入字符串和right serial是否匹配

将初始化v13的十六进制转换为字符串即可。

技术图片

 

 

 

 

open-source

直接给的源码

 

技术图片

 

 

 

第29行计算flag,第32行代码输出十六进制形式

 

    printf("Brr wrrr grr\\n");

    unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;

    printf("Get your key: ");
    printf("%x\\n", hash);
    return 0;

技术图片

 

 

 

然后看看我们需要满足的条件

if (argc != 4) 
        printf("what?\\n");
        exit(1);
    

    unsigned int first = atoi(argv[1]);
    if (first != 0xcafe) 
        printf("you are wrong, sorry.\\n");
        exit(2);
    

    unsigned int second = atoi(argv[2]);
    if (second % 5 == 3 || second % 17 != 8) 
        printf("ha, you won‘t get it!\\n");
        exit(3);
    

    if (strcmp("h4cky0u", argv[3])) 
        printf("so close, dude!\\n");
        exit(4);
    

 

first=0xcafe

second = 25

argv[3]=“h4cky0u”

 

ok  写个c++打印下flag

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[]) 

    int first = 0xcafe;
    int second = 25;
    argv[3] = "h4cky0u";

    printf("Brr wrrr grr\\n");

    unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;

    printf("Get your key: ");
    printf("%x\\n", hash);

    system("PAUSE");
    return 0;

技术图片

 

 

 

 

 

 

 

simple-unpack

查壳

elf格式文件  upx壳

技术图片

 

 

 

首先ida查看字符串直接可以找到

技术图片

 

 

当然也可以

直接kali upx脱壳

技术图片

 

 打开脱壳后的 main函数

技术图片

 

以上是关于攻防世界(XCTF)逆向部分write up的主要内容,如果未能解决你的问题,请参考以下文章

攻防世界(XCTF)WEB(进阶区)write up

攻防世界(XCTF)WEB(进阶区)write up

XCTF-攻防世界CTF平台-Reverse逆向类——57re5-packed-movement

XCTF-攻防世界CTF平台-Reverse逆向类——1Mysterious

XCTF-攻防世界CTF平台-Reverse逆向类——31hackme

XCTF-攻防世界CTF平台-Reverse逆向类——59mfc逆向-200