攻防世界reverse新手练习

reversing 专栏收录该内容
4 篇文章 0 订阅

0x01 re1

用ida打开进行静态分析,按F5进行反编译

注意标黄色标记的地方,输入的字符会保存在 v9,这个字符串会跟 v5 进行比较,如果两个字符串相等,那么就会输出 flag get,这说明 flag 是已经保存在程序中的

我们在strings window(按shift+F12)中可以看到这几个字符串,我们可以推测flag包含DUTCTF字符串,所以在命令台中输入:

strings re1.exe | findstr DUTCTF

图中字符串就是我们要找的flag

0x02 game

打开game.exe

意思是有n盏灯,m是灯的状态,m为1灯是开,m为0灯是关。一开始灯全部都是关的。现在输入一个序列对n盏灯进行开关使它们都是亮的就可以找到flag,开关第n盏灯时,会影响到n-1和n+1盏灯的状态。

上面这些都不是重点。

打开strings window

可以看到done!!! the flag is,鼠标点击这行,会跳转到下面

然后右键list cross reference to,跳转后F5,可以看到下面代码

int sub_45E940()
{
  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_45A7BE("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_45A7BE("%s\n");
}

上面的代码就是求flag的过程,我们可以编写一个Python脚本来模仿这个过程

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)

得到flag是zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}

0x03 Hello,CTF

ida打开静态分析,按F5以后

int __cdecl main(int argc, const char **argv, const char **envp)
{
  signed int v3; // ebx
  char v4; // al
  int result; // eax
  int v6; // [esp+0h] [ebp-70h]
  int v7; // [esp+0h] [ebp-70h]
  char v8; // [esp+12h] [ebp-5Eh]
  char v9[20]; // [esp+14h] [ebp-5Ch]
  char v10; // [esp+28h] [ebp-48h]
  __int16 v11; // [esp+48h] [ebp-28h]
  char v12; // [esp+4Ah] [ebp-26h]
  char v13; // [esp+4Ch] [ebp-24h]

  strcpy(&v13, "437261636b4d654a757374466f7246756e");
  while ( 1 )
  {
    memset(&v10, 0, 0x20u);
    v11 = 0;
    v12 = 0;
    sub_40134B(aPleaseInputYou, v6);
    scanf(aS, v9);
    if ( strlen(v9) > 0x11 )
      break;
    v3 = 0;
    do
    {
      v4 = v9[v3];
      if ( !v4 )
        break;
      sprintf(&v8, asc_408044, v4);
      strcat(&v10, &v8);
      ++v3;
    }
    while ( v3 < 17 );
    if ( !strcmp(&v10, &v13) )
      sub_40134B(aSuccess, v7);
    else
      sub_40134B(aWrong, v7);
  }
  sub_40134B(aWrong, v7);
  result = stru_408090._cnt-- - 1;
  if ( stru_408090._cnt < 0 )
    return _filbuf(&stru_408090);
  ++stru_408090._ptr;
  return result;
}

注意这几句代码:

strcpy(&v13, "437261636b4d654a757374466f7246756e");

scanf(aS, v9);
    if ( strlen(v9) > 0x11 )
      break;

strcat(&v10, &v8);

while ( v3 < 17 );
    if ( !strcmp(&v10, &v13) )
      sub_40134B(aSuccess, v7);

我们输入的字符串最终为v10,只要v10和v13一样我们就可以得到flag

下面编写求v13的python脚本

a = [0x43,0x72,0x61,0x63,0x6b,0x4d,0x65,0x4a,0x75,0x73,0x74,0x46,0x6f,0x72,0x46,0x75,0x6e]
c = ""
for x in a:
    c += chr(x)
print(c)

然后运行

所以得到的字符串就是flag

0x04 open-source

这题感觉跟逆向没什么关系。

查看源代码就可以很容易做出来了,不详细讲解,直接贴图

0x05 simple-unpack

看标题就知道这题是要脱壳。先查看一下是什么壳

winHex打开

是UPX壳,在命令行中输入upx -d(电脑没装upx,要先安装),然后把脱壳后的程序进行ida分析,就可以找到flag

0x06 logmein

这是简单的算法逆向题

ida静态分析,找到main函数(没找到就重新打开),然后按F5

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();
}

关键的算法就是在for循环那,写个cpp模拟一下

#include <iostream>
#include <cstdio>
using namespace std;

int main()
{
	long long a = 28537194573619560;
	char * p = (char*)&a;
	char b[] = ":\"AL_RT^L*.?+6/46";
	for(int i = 0;b[i]!=0;i++){
		b[i] = b[i]^p[i%7];
	}
	cout<<b<<endl;
}

输出的就是flag

0x07 insanity

这题没什么好说的,直接shift+F12打开strings window,就可以直接看到flag了

0x08 no-strings-attached

(这题是真的难)

先打开ida静态分析

这是main函数,按F5

可以看到main函数调用多个子函数,我们看一下authenticate()这个函数(authenticate中文意思就是鉴定)

里面有个decrypt(解密的意思,英语好是有多么重要)函数,所以s2应该就是我们要的字符串。要拿到s2,我们进行动态分析。

有两种动态分析的方法:

一、ida remote linux debugger

首先要进行环境的配置,如何配置看下面的连接,也可以看《ida pro权威指南》

https://bbs.pediy.com/thread-247830-1.htm

http://www.cnblogs.com/trojan-z/p/6885919.html

开始进行动态调试,先找到authenticate函数,可以打开names window来找这个函数,然后打开,在下图的位置设置断点

按F9

在这窗口,右键选择synchronized with,接着选择eax。

为什么要看eax,我们可以看一下还没有反编译的authenticate

因为解密后的s2就存放在eax。

同步好后,hex view中就可以看到下图字符串就是我们要找的flag

二、利用linux GDB来动态调试

一定要用linux中的GDB来调试

按图中的步骤输入,设置断点(n是next b是breakpoint s是step n是单步不进入s是单步进入)。接着输入下图命令

00000以前的就是我们要找的flag,写一个脚本将16进制ascii码转成字符就行了。也可以输入x /100c $eax会自动输出成对应的字符。

0x09 csaw2013reversing2

https://github.com/VulnHub/ctf-writeups/blob/master/2014/csaw/csaw2013reversing2-dot-exe.md

上面是一位大神的讲解用英文的,我这里就做一下翻译

首先还是ida静态分析

我们可以看到下面这样一个调用,判断程序是否是由debugger在运行,如果是就走右边那个分支。

我们看一下右边的分支

程序到int 3就会终止。后面的语句也就都不执行了,但是后面还有一个调用子函数的语句不会执行。我们进入那个子函数看一下,那个子函数是在做什么?

It looked like it was XORing the contents of [eax+ecx*4] with the value in esi in a loop, which made me suspect that it was the function responsible for decrypting the flag. I went ahead and ran the program in IDA's debugger and as expected, I hit the software breakpoint which terminated the program.

接着我们就可以动态去调试,看一下会发生什么。在int3前设置断点,按F9运行,程序会停在下图

我们可以将光标放在call sub_10d1000的位置按F4,也可以通过修改EIP使程序执行那条语句(会有一个弹窗选择no)

我们直接执行下图的循环

然后注意hex view,要将hex view和edx同步,下图就是得到flag的过程。

还有另外一种做法,就不详细说明了

0x0A getit

ida64静态分析,按F5生成pseudocode

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v3; // al
  __int64 v5; // [rsp+0h] [rbp-40h]
  int i; // [rsp+4h] [rbp-3Ch]
  FILE *stream; // [rsp+8h] [rbp-38h]
  char filename[8]; // [rsp+10h] [rbp-30h]
  unsigned __int64 v9; // [rsp+28h] [rbp-18h]

  v9 = __readfsqword(0x28u);
  LODWORD(v5) = 0;
  while ( (signed int)v5 < strlen(s) )
  {
    if ( v5 & 1 )
      v3 = 1;
    else
      v3 = -1;
    *(&t + (signed int)v5 + 10) = s[(signed int)v5] + v3;
    LODWORD(v5) = v5 + 1;
  }
  strcpy(filename, "/tmp/flag.txt");
  stream = fopen(filename, "w");
  fprintf(stream, "%s\n", u, v5);
  for ( i = 0; i < strlen(&t); ++i )
  {
    fseek(stream, p[i], 0);
    fputc(*(&t + p[i]), stream);
    fseek(stream, 0LL, 0);
    fprintf(stream, "%s\n", u);
  }
  fclose(stream);
  remove(filename);
  return 0;
}

下面是重点代码

LODWORD(v5) = 0;
  while ( (signed int)v5 < strlen(s) )
  {
    if ( v5 & 1 )
      v3 = 1;
    else
      v3 = -1;
    *(&t + (signed int)v5 + 10) = s[(signed int)v5] + v3;
    LODWORD(v5) = v5 + 1;
  }

可以看出将s中的值赋给了t,然后最后是将t写入文件flag.txt中,我们看一下s和t分别是什么:

现在我们可以编写脚本来解出flag

v5 = 0
s = 'c61b68366edeb7bdce3c6820314b7498'
t = ['S','h','a','r','i','f','C','T','F','{','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','?','}']
v3 = 0
l = len(s)
while(v5 < l):
    if( v5 & 1 ):
        v3 = 1
    else:
        v3 = -1
    t[10+v5] = chr(ord(s[v5])+v3)
    v5 += 1
c = ''
for x in t:
    c+=x
print(c)

0x0B python-trade

是一个pyc文件,用python反编译工具反编译后可以看到代码https://tool.lu/pyc/

import base64

def encode(message):
    s = ''
    for i in message:
        x = ord(i) ^ 32
        x = x + 16
        s += chr(x)
    
    return base64.b64encode(s)

correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
flag = ''
print 'Input flag:'
flag = raw_input()
if encode(flag) == correct:
    print 'correct'
else:
    print 'wrong'

编写相应的脚本

import base64

buf = base64.b64decode('XlNkVmtUI1MgXWBZXCFeKY+AaXNt')
flag = ''
for i in buf:
    i -= 16
    i ^= 32
    flag += chr(i)

print(flag)

0x0C

这题是有点难的,是南邮ctf re5,是算法逆向,参考下面的文章

https://blog.csdn.net/xiangshangbashaonian/article/details/78883611

https://my.oschina.net/u/3763247/blog/1805781

最主要是看懂下面的流程

我们看一下每个子程序在做什么

这是一个向上或者向右走的指令,其他三个类似

往下走,可以看到又调用了一个子函数sub_400690

看汇编语言会更清楚

三幅图结合在一起看就可以看出来了,是判断有没有走到某个位置。

在调用前还有一条语句是mov     edi, offset asc_601060,我们看一下601060

我们可以看出是以8列为一行的一个图(迷宫),最终的目标是走到#,从下图可以分析出来。

我们可以假设.0对应上下,Oo对应左右

路径是:右下右右下下左下下下右右右右上上左左

o0oo00O000oooo..OO,flag就是加nctf{}

  • 5
    点赞
  • 5
    评论
  • 13
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值