暑假记录写题篇

攻防世界基础题(12道)

第一题

在这里插入图片描述
附件下载给出源码:

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

int main(int argc, char *argv[]) {
    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);
    }

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

分析源码:
发现要满足几个条件程序才能顺利进行,我们需要做的就是找出参数带入后面的hash式子,就能得出答案了。
1、 首先满足first的值为十六进制的0xcafe,通过在线网站得出十进制值为51966
分享一下网站吧:https://tool.lu/hexconvert/
在这里插入图片描述
2、 满足second%5的值不等于3,并且second%17的值等于8,不难看出25就符合这个条件。
在这里插入图片描述
3、 不难看出我们需要的值为字符串h4cky0u的长度,值为7
在这里插入图片描述

答案揭晓

现在我们知道了所有的参数值了,经过我的修改如下:

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

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

    printf("Brr wrrr grr\n");

    unsigned int hash = 51966 * 31337 + ((25 % 17) * 11 + 7) - 1615810207;

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

得出结果如下:

在这里插入图片描述

第二题

在这里插入图片描述
考脱壳处理,附件是一个二进制文件放到pe里发现经过upx壳处理,如图:
在这里插入图片描述
kali自带upx,打开虚拟机里面的kali,将文件拖进去执行代码:

upx -d 文件的绝对路径

在这里插入图片描述

答案揭晓

将脱过壳的二进制文件拖进ida分析,搜索字符串flag,得出结果。
在这里插入图片描述

第三题

在这里插入图片描述
先放入pe 查壳和分析程序,发现是一个64位ELF文件
在这里插入图片描述
接着放入ida分析,先重main函数开始,F5查看伪代码
在这里插入图片描述
分析这一步可知密码的长度必须大于v8字符串的长度
在这里插入图片描述
通过查看代码看出v8字符串长度为17
在这里插入图片描述
从这段代码中可以看出密码的长度等于v8字符串的长度
在这里插入图片描述
接下来就是关键的算法了,可以知道算出算法就能得到答案
在这里插入图片描述

答案揭晓

源码:

int main()
{
	int i;
	long long v7=28537194573619560LL; 
	char v8[]=":\"AL_RT^L*.?+6/46";
	char final_string[20];
	for(i=0;i<17;i++)
	{
		final_string[i]=(char)(*((BYTE*)&v7+i%7)^v8[i]);
		printf("%c",final_string[i]);
	}
	return 0;
 } 

在这里插入图片描述

第四题

在这里插入图片描述
打开附件是一个二进制文件,先拖入pe里查看,发现是一个32位的ELF文件
在这里插入图片描述
将文件拖入32位ida里面分析,当我按下Shift+F12,发现了神秘的flag,如图:
在这里插入图片描述
奇怪的flag获得方式增加了,不过这都第四题了,不应该越来越难吗?

答案揭晓

然后我深入了解后发现这道题的意思大概是让我们学会找关键字,不能死板,如图:
在这里插入图片描述
这是main函数的伪代码,发现里面没什么算法,但是有一个关键词strs,我们接着双击strs,发现了flag,这才是正解,哈哈哈哈!
在这里插入图片描述

第五题

在这里插入图片描述
附件下载后是一个pyc文件,需要用到在线python反编译器解读,源码(python2):

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'

网站链接:https://tool.lu/pyc/
分析一下代码,得出改程序需要逆向思维,将给出的字符串 **‘XlNkVmtUI1MgXWBZXCFeKY+AaXNt’**通过逆向得出flag。

答案揭晓

我写的源码(python2):

import base64
flag=base64.b64decode('XlNkVmtUI1MgXWBZXCFeKY+AaXNt')
x=''
for i in flag:
    x+=chr((ord(i)-16)^32)
print("flag:",x)

首先明白base64模块里面的加密、解密代码,odr() :将字符串转化成ASCII码,chr():将ASCII码转化成字符串,然后将字符串解密,通过逆向算法来求出最后的flag。

第六题

在这里插入图片描述
放入pe里面发现是个32位exe程序
在这里插入图片描述
打开是一个小游戏,这一题的解法很多,可以通过玩游戏获得,也可以分析程序算法获得,这个小游戏很好玩,我两分钟就通关了,接下来分析算法
在这里插入图片描述
接着放入ida里分析程序
在这里插入图片描述
主要伪代码如下,通过分析我们知道当if结果都为1时会进入sub_457AB4()函数:

void __cdecl main_0()
{
  char v0; // ST08_1
  char v1; // ST08_1
  char v2; // ST08_1
  char v3; // ST08_1
  char v4; // ST08_1
  char v5; // ST08_1
  char v6; // ST08_1
  char v7; // ST08_1
  char v8; // ST08_1
  char v9; // ST08_1
  char v10; // ST08_1
  char v11; // ST08_1
  char v12; // ST08_1
  char v13; // ST08_1
  char v14; // ST08_1
  char v15; // ST08_1
  char v16; // ST08_1
  char v17; // ST08_1
  char v18; // [esp+0h] [ebp-FCh]
  char v19; // [esp+0h] [ebp-FCh]
  signed int i; // [esp+DCh] [ebp-20h]
  int v21; // [esp+F4h] [ebp-8h]

  sub_45A7BE((int)&unk_50B110, v18);
  sub_45A7BE((int)&unk_50B158, v0);
  sub_45A7BE((int)&unk_50B1A0, v1);
  sub_45A7BE((int)&unk_50B1E8, v2);
  sub_45A7BE((int)&unk_50B230, v3);
  sub_45A7BE((int)&unk_50B278, v4);
  sub_45A7BE((int)&unk_50B2C0, v5);
  sub_45A7BE((int)&unk_50B308, v6);
  sub_45A7BE((int)&unk_50AFD0, v7);
  sub_45A7BE((int)"|              by 0x61                                 |\n", v8);
  sub_45A7BE((int)"|                                                      |\n", v9);
  sub_45A7BE((int)"|------------------------------------------------------|\n", v10);
  sub_45A7BE(
    (int)"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",
    v11);
  sub_45A7BE((int)"Now you can input n to change its state\n", v12);
  sub_45A7BE(
    (int)"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 will be changed too\n",
    v13);
  sub_45A7BE((int)"When all lamps are on,flag will appear\n", v14);
  sub_45A7BE((int)"Now,input n \n", v15);
  while ( 1 )
  {
    while ( 1 )
    {
      sub_45A7BE((int)"input n,n(1-8)\n", v19);
      sub_459418();
      sub_45A7BE((int)"n=", v16);
      sub_4596D4("%d", &v21);
      sub_45A7BE((int)"\n", v17);
      if ( v21 >= 0 && v21 <= 8 )
        break;
      sub_45A7BE((int)"sorry,n error,try again\n", v19);
    }
    if ( v21 )
    {
      sub_4576D6(v21 - 1);
    }
    else
    {
      for ( i = 0; i < 8; ++i )
      {
        if ( (unsigned int)i >= 9 )
          j____report_rangecheckfailure();
        byte_532E28[i] = 0;
      }
    }
    j__system("CLS");
    sub_458054();
    if ( byte_532E28[0] == 1
      && byte_532E28[1] == 1
      && byte_532E28[2] == 1
      && byte_532E28[3] == 1
      && byte_532E28[4] == 1
      && byte_532E28[5] == 1
      && byte_532E28[6] == 1
      && byte_532E28[7] == 1 )
    {
      sub_457AB4();
    }
  }
}

sub_457AB4()函数里面应该就是flag的主要算法,如下:

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

答案揭晓

通过小游戏得出答案
在这里插入图片描述
下面是我写的python脚本,跑出flag:

str1=[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]
str2=[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]
str3=''
for i in range(56):
    str1[i]^=str2[i]
    str1[i]^=0x13
    str3+=chr(str1[i])
print(str3)

在这里插入图片描述

第七题

在这里插入图片描述
附件是一个exe程序,将程序放入pe里查看,是一个32位exe文件
在这里插入图片描述
放入ida里面分析,又是一个算法,看着比较复杂,分析分析。

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

将字符串复制到v13
在这里插入图片描述
这里知道输入的字符串不能大于17
在这里插入图片描述
将输入的字符串以16进制复制到v10里
在这里插入图片描述
判断输入字符串的长度与给的字符串是否一致,如果一致则输入正确
在这里插入图片描述

答案揭晓

将十六进制转化成普通字符串就是flag
转化链接:http://www.bejson.com/convert/ox2str/
在这里插入图片描述

第八题

在这里插入图片描述
打开附件是一个二进制文件,先放入pe中分析,是一个64位ELF文件
在这里插入图片描述
将文件放入64位ida里面分析,伪代码如下:

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

主要算法:
在这里插入图片描述
将u的值写入flag.txt,值得注意的是写入的值并不是我们通过算法得出的值v5
在这里插入图片描述
通过查找发现 u,s,t 的值如下:
在这里插入图片描述
注意t的值前面还有一个 53h 转化成字符串为 S
在这里插入图片描述
很明显这是个坑,正确的flag应该是v5的值,还不止这些,如果直接运行里面的内容还会被转移:
在这里插入图片描述
这个题的一种思路就是在remove这里下断点然后在linux里面执行,会在tmp文件夹里生存flag.txt文件,儿里面的值确实一堆*号就是上面提的u的值,所以社会险恶处处是坑,还是直接写Python脚本来的实在。

答案揭晓

Python3脚本如下:

s='c61b68366edeb7bdce3c6820314b7498'
flag='SharifCTF{'
v5=0

while v5<len(s):
    if (v5 & 1):
        v3=1
    else:
        v3=-1
    flag+=chr(ord(s[v5])+v3)
    v5+=1
print(flag+'}')

在这里插入图片描述

第九题

在这里插入图片描述
附件是一个exe文件打开如图:
在这里插入图片描述
放入pe里分析一下,是个32位的文件
在这里插入图片描述
放入32位ida里面进一步分析,main函数主要伪代码:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  __int128 v5; // [esp+0h] [ebp-44h]
  __int64 v6; // [esp+10h] [ebp-34h]
  int v7; // [esp+18h] [ebp-2Ch]
  __int16 v8; // [esp+1Ch] [ebp-28h]
  char v9; // [esp+20h] [ebp-24h]

  _mm_storeu_si128((__m128i *)&v5, _mm_loadu_si128((const __m128i *)&xmmword_413E34));
  v7 = 0;
  v6 = qword_413E44;
  v8 = 0;
  printf(&byte_413E4C);
  printf(&byte_413E60);
  printf(&byte_413E80);
  scanf("%s", &v9);
  v3 = strcmp((const char *)&v5, &v9);
  if ( v3 )
    v3 = -(v3 < 0) | 1;
  if ( v3 )
    printf(aFlag);
  else
    printf((const char *)&unk_413E90);
  system("pause");
  return 0;
}

这里应该是将下面的值赋给了v5
在这里插入图片描述
v6的值经过处理是下面的结果
在这里插入图片描述

答案揭晓

将两个字符串连起来,通过输入逆向后字符串验证,通过就显示get flag √
在这里插入图片描述
在这里插入图片描述

第十题

在这里插入图片描述
附件是一个32位的ELF文件,代表可以在linux下运行。在这里插入图片描述
放入32位ida里分析一下
在这里插入图片描述
发现了关键函数,里面有一个英文加密很显眼
在这里插入图片描述
加密函数源码如下:

wchar_t *__cdecl decrypt(wchar_t *s, wchar_t *a2)
{
  size_t v2; // eax
  signed int v4; // [esp+1Ch] [ebp-1Ch]
  signed int i; // [esp+20h] [ebp-18h]
  signed int v6; // [esp+24h] [ebp-14h]
  signed int v7; // [esp+28h] [ebp-10h]
  wchar_t *dest; // [esp+2Ch] [ebp-Ch]

  v6 = wcslen(s);
  v7 = wcslen(a2);
  v2 = wcslen(s);
  dest = (wchar_t *)malloc(v2 + 1);
  wcscpy(dest, s);
  while ( v4 < v6 )
  {
    for ( i = 0; i < v7 && v4 < v6; ++i )
      dest[v4++] -= a2[i];
  }
  return dest;
}

通过简单的寻找汇编线索,发现加密函数储存的flag值在eax中
在这里插入图片描述

得学新技能了,,,动态调试,用GDB来动态调试取出对应寄存器里的值
GDB使用命令:https://www.cnblogs.com/Mayfly-nymph/p/11403150.html

答案揭晓

时隔两天,我又回来了,大家用gdb的时候千万别用绝对路径打开文件,尽量用 ./文件名 的形式打开文件,这样不会报错,如图(顺手在加密函数那里下一个断点):
在这里插入图片描述
r 代表运行程序,运行到之前下的断点,(这里权限不够了记得给文件加上权限)
在这里插入图片描述
在这里插入图片描述
n代表运行一步
在这里插入图片描述
我们通过看汇编已经知道了运行过decrypt函数后将字符串储存在eax寄存器中,代码:

x/6sw $eax

在这里插入图片描述
x:表示查看寄存器中的数值
6:显示6行数据
s:字符串的形式打印
w:word的缩写,代表4字节

第十一题

在这里插入图片描述
看题目可能涉及到编码的问题,先下载附件,是一个exe文件,运行如图:
在这里插入图片描述
放入PE里查看,是一个32位的文件
在这里插入图片描述
放入32位ida立面分析,F5查看伪代码:

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // ecx
  CHAR *lpMem; // [esp+8h] [ebp-Ch]
  HANDLE hHeap; // [esp+10h] [ebp-4h]

  hHeap = HeapCreate(0x40000u, 0, 0);
  lpMem = (CHAR *)HeapAlloc(hHeap, 8u, MaxCount + 1);
  memcpy_s(lpMem, MaxCount, &unk_409B10, MaxCount);
  if ( sub_40102A() || IsDebuggerPresent() )
  {
    __debugbreak();
    sub_401000(v3 + 4, (int)lpMem);
    ExitProcess(0xFFFFFFFF);
  }
  MessageBoxA(0, lpMem + 1, "Flag", 2u);
  HeapFree(hHeap, 0, lpMem);
  HeapDestroy(hHeap);
  ExitProcess(0);
}

发现程序主要是由if语句判断,如果跳过if语句会直接弹出MessageBoxA窗口然后就会出现乱码。
接着分析框架:
在这里插入图片描述
清晰的知道了大致框架,可以通过od动态调试将程序先跳转到401096,通过401000函数进行解码,
在这里插入图片描述
在这里插入图片描述
并且把断点 int3 改成 nop
在这里插入图片描述
在这里插入图片描述
继续修改,将跳转到4010EF改成4010B9弹出解码后的flag:
在这里插入图片描述

答案揭晓

运行软件得出flag:
在这里插入图片描述

第十二题

在这里插入图片描述
描述没有看出什么端倪,下载附件,是一个二进制文件,放入PE查看:
在这里插入图片描述
是一个64位的ELF文件,可以放入64位ida里面F5分析一下伪代码(这次的解释直接备注进代码了):

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  const char *v3; // rsi
  signed __int64 v4; // rbx
  signed int v5; // eax
  char v6; // bp
  char v7; // al
  const char *v8; // rdi
  __int64 v10; // [rsp+0h] [rbp-28h]

  v10 = 0LL;
  puts("Input flag:");
  scanf("%s", &s1, 0LL);
  if ( strlen(&s1) != 24 || (v3 = "nctf{", strncmp(&s1, "nctf{", 5uLL)) || *(&byte_6010BF + 24) != 125 )   #输入的flag长度为24,前五个字符为'nctf{'(意思是格式为nctf{}),最后一个条件的意思是char(address(byte_6010BF))+24) 等于125,也就是说改地址加24里面的值为125
  {
LABEL_22:
    puts("Wrong flag!");
    exit(-1);    #程序结束
  }
  v4 = 5LL;       #v4=5
  if ( strlen(&s1) - 1 > 5 )  #字符串至少为6个,即'nctf{}'
  {
    while ( 1 )
    {
      v5 = *(&s1 + v4);   #取s1[5]位置的ASCII值
      v6 = 0;
      if ( v5 > 78 )
      {
        v5 = (unsigned __int8)v5;
        if ( (unsigned __int8)v5 == 79 )   
        {
          v7 = sub_400650((char *)&v10 + 1);  v7=1
          goto LABEL_14;
        }
        if ( v5 == 111 )
        {
          v7 = sub_400660((char *)&v10 + 1, v3);
          goto LABEL_14;
        }
      }
      else
      {
        v5 = (unsigned __int8)v5;
        if ( (unsigned __int8)v5 == 46 )
        {
          v7 = sub_400670(&v10, v3);
          goto LABEL_14;
        }
        if ( v5 == 48 )
        {
          v7 = sub_400680(&v10, v3);
LABEL_14:
          v6 = v7;
          goto LABEL_15;
        }
      }
LABEL_15:
      v3 = (const char *)HIDWORD(v10);
      if ( !(unsigned __int8)sub_400690(asc_601060, HIDWORD(v10), (unsigned int)v10) )
        goto LABEL_22;
      if ( ++v4 >= strlen(&s1) - 1 )
      {
        if ( v6 )
          break;
LABEL_20:
        v8 = "Wrong flag!";
        goto LABEL_21;
      }
    }
  }
  if ( asc_601060[8 * (signed int)v10 + SHIDWORD(v10)] != 35 )
    goto LABEL_20;
  v8 = "Congratulations!";
LABEL_21:
  puts(v8);
  return 0LL;
}

迷宫问题:https://ctf-wiki.github.io/ctf-wiki/reverse/maze/maze/
通过条件和题目介绍我们大致知道这是个迷宫,需要输入’O’,‘o’,’.’,‘0’,来控制移动走出迷宫,
发现一段迷宫字符串
在这里插入图片描述
由迷宫代码猜测是一段8*8的迷宫,如图:
在这里插入图片描述
有如下代码可知如果不为空格或者**#**则程序终止
在这里插入图片描述
通过如下代码知道口为坐标(0,0)
在这里插入图片描述

通过如图代码知道出口为 #
在这里插入图片描述

答案揭晓

现在的实力只能知道管上下左右的,但是原理还不了解,'O’是左,'o’是右,
'.'是上,'0’是下,flag为:nctf{o0oo00O000oooo…OO}

BUUCTF练题

第一题(1分)

在这里插入图片描述
先来一道简单的练练手,附件是一个exe文件打开后能输入,没有什么特殊提示:
在这里插入图片描述
放入PE里分析一波,是个64位的
在这里插入图片描述
用64位ida分析伪代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int b; // [rsp+28h] [rbp-8h]
  int a; // [rsp+2Ch] [rbp-4h]

  _main();
  scanf("%d%d", &a, &b);
  if ( a == b )
    printf("flag{this_Is_a_EaSyRe}");
  else
    printf("sorry,you can't get flag");
  return 0;
}

果然简单题就是不一样,简单明了

答案揭晓

简单明了,flag{this_Is_a_EaSyRe}

第二题(1分)

在这里插入图片描述
下载附件放入PE查看,是一个64位的elf程序
在这里插入图片描述
放入64位ida里面分析伪代码:

  int result; // eax
  int stat_loc; // [rsp+4h] [rbp-3Ch]
  int i; // [rsp+8h] [rbp-38h]
  __pid_t pid; // [rsp+Ch] [rbp-34h]
  char s2; // [rsp+10h] [rbp-30h]
  unsigned __int64 v8; // [rsp+28h] [rbp-18h]

  v8 = __readfsqword(0x28u);
  pid = fork();
  if ( pid )
  {
    argv = (const char **)&stat_loc;
    waitpid(pid, &stat_loc, 0);
  }
  else
  {
    for ( i = 0; i <= strlen(&flag); ++i )
    {
      if ( *(&flag + i) == 105 || *(&flag + i) == 114 )
        *(&flag + i) = 49;
    }
  }
  printf("input the flag:", argv);
  __isoc99_scanf("%20s", &s2);
  if ( !strcmp(&flag, &s2) )
    result = puts("this is the right flag!");
  else
    result = puts("wrong flag!");
  return result;
}

答案揭晓

大致意思是把flag字符串里面的 i 和r换成数字 1 ,即为正确的flag:
在这里插入图片描述
正确的flag为:flag{hack1ng_fo1_fun}

第三题(1分)

在这里插入图片描述
下载附件后得到一个exe文件,运行一下如图:
在这里插入图片描述
放入PE里查看,是一个32位exe程序,加了upx壳
在这里插入图片描述
接着放入kali进行upx脱壳处理:
在这里插入图片描述
接着放入32位ida里面分析,伪代码如下:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  char v4; // [esp+12h] [ebp-3Ah]
  __int16 v5; // [esp+20h] [ebp-2Ch]
  __int16 v6; // [esp+22h] [ebp-2Ah]

  __main();
  strcpy(&v4, "HappyNewYear!");
  v5 = 0;
  memset(&v6, 0, 0x1Eu);
  printf("please input the true flag:");
  scanf("%s", &v5);
  if ( !strncmp((const char *)&v5, &v4, strlen(&v4)) )
    result = puts("this is true flag!");
  else
    result = puts("wrong!");
  return result;
}

答案揭晓

大致意思是判断我们输入的字符串是否和v4相等,如果相等输出:this is true flag!,如果不相等输出 wrong!
所以flag为:flag{HappyNewYear!}

第四题(1分)

在这里插入图片描述
附件是一个exe文件,打开如图:
在这里插入图片描述
BUU还真是心机啊,不得不拿出我的pe和ida了
在这里插入图片描述
32位无壳exe文件,可以用32位ida分析了,伪代码如下:

int __cdecl main_0()
{
  int result; // eax
  char v1; // [esp+4Ch] [ebp-Ch]
  const char *v2; // [esp+50h] [ebp-8h]
  int v3; // [esp+54h] [ebp-4h]

  v3 = 5;
  v2 = "DBAPP{49d3c93df25caad81232130f3d2ebfad}";
  while ( v3 >= 0 )
  {
    printf(&byte_4250EC, v3);
    sub_40100A();
    --v3;
  }
  printf(asc_425088);
  v1 = 1;
  scanf("%c", &v1);
  if ( v1 == 89 )
  {
    printf(aOd);
    result = sub_40100A();
  }
  else
  {
    if ( v1 == 78 )
      printf(&byte_425034);
    else
      printf(&byte_42501C);
    result = sub_40100A();
  }
  return result;
}

答案揭晓

BUU啊BUU不愧是你,搞这么简单,我分析了一遍发现没有结果,flag就是呢个自变量,有点太简单了,flag都是显而易见,flag{49d3c93df25caad81232130f3d2ebfad}

第五题(1分)

在这里插入图片描述
下载附件是一个exe文件,打开看一下,是一个比大小的游戏,结果如图,直接****,我直 呼正道の光
在这里插入图片描述
放入PE里查看一下,是个64位的普通exe文件
在这里插入图片描述
放入64位ida里面,shift+F12检索关键字符串找出flag

答案揭晓

在这里插入图片描述

第6题(1分)

在这里插入图片描述
附件是一个apk文件,我还没学过安卓逆向,java也没学过,摸索了半天后,终于,在学长的指导下,下载了jeb安卓反编译器。

答案揭晓

搜索字符串后得到flag如图:
在这里插入图片描述

第七题(1分)

在这里插入图片描述
附件有两个二进制文件,放入PE里查看,其中一个如图:
在这里插入图片描述
另一个如图:
在这里插入图片描述
PE好像看不出来什么,将第一个文件放入ida64位里分析伪代码:

  __int64 v7; // [rsp+148h] [rbp-8h]

  memset(v6, 0, 0x100uLL);
  v3 = (char *)256;
  printf("Input your flag:\n", 0LL);
  get_line(v6, 0x100u);
  if ( strlen(v6) != 33 )
    goto LABEL_12;
  for ( i = 1; i < 33; ++i )
    v6[i] ^= v6[i - 1];
  v3 = global;
  if ( !strncmp(v6, global, 0x21uLL) )
    printf("Success", v3);
  else
LABEL_12:
    printf("Failed", v3);
  result = __stack_chk_guard;
  if ( __stack_chk_guard == v7 )
    result = 0;
  return result;
}

大致意思是v6的长度为33且前一个和后一个进行异或,异或完成后和v3比较,正确即为成功,逆着来就是将v3字符串倒着异或一遍就是flag了,注意v3字符串即 global 里面的数据取出来即可。
在这里插入图片描述

在这里插入图片描述

答案揭晓

我写的python3脚本:

str=[102,  10, 107,  12, 119,  38,  79,  46,  64,  17, 120,  13,  90,  59,  85,  17, 112,  25,  70,  31, 118,  34,  77,  35,  68,  14, 103,   6, 104,  15, 71,  50,  79,0]
x=''
for i in range(1,33):
    str[i]^=str[i+1]
    x+=chr(str[i])
print(x)

在这里插入图片描述

第八题(1分)

在这里插入图片描述
附件是一个exe文件放入PE里查看:
在这里插入图片描述
放入32位ida分析伪代码:

__int64 __cdecl main_0()
{
  int v0; // eax
  const char *v1; // eax
  size_t v2; // eax
  int v3; // edx
  __int64 v4; // ST08_8
  signed int j; // [esp+DCh] [ebp-ACh]
  signed int i; // [esp+E8h] [ebp-A0h]
  signed int v8; // [esp+E8h] [ebp-A0h]
  char Dest[108]; // [esp+F4h] [ebp-94h]
  char Str; // [esp+160h] [ebp-28h]
  char v11; // [esp+17Ch] [ebp-Ch]

  for ( i = 0; i < 100; ++i )
  {
    if ( (unsigned int)i >= 0x64 )
      j____report_rangecheckfailure();
    Dest[i] = 0;
  }
  sub_41132F("please enter the flag:");
  sub_411375("%20s", (unsigned int)&Str);
  v0 = j_strlen(&Str);
  v1 = (const char *)sub_4110BE((int)&Str, v0, (int)&v11);
  strncpy(Dest, v1, 0x28u);
  v8 = j_strlen(Dest);
  for ( j = 0; j < v8; ++j )
    Dest[j] += j;
  v2 = j_strlen(Dest);
  if ( !strncmp(Dest, Str2, v2) )
    sub_41132F("rigth flag!\n");
  else
    sub_41132F("wrong flag!\n");
  HIDWORD(v4) = v3;
  LODWORD(v4) = 0;
  return v4;
}

经过查阅得知算法是base64加密,通过分析得知Str2中的字符串通过将上面的算法逆向从而得到正确的flag,Str2中的字符串如图:
在这里插入图片描述

答案揭晓

我写的python3脚本如下:

import base64
list1=['e', '3', 'n', 'i', 'f', 'I', 'H', '9', 'b', '_', 'C', '@', 'n', '@', 'd', 'H']
c=''
d=0
for i in range(16):
    x=ord(list1[i])
    x=x-d
    c+=chr(x)
    d+=1
print(base64.b64decode(c))

在这里插入图片描述
flag{i_l0ve_you}

第九题(1分)

在这里插入图片描述
打开是一个exe程序,运行如图:
在这里插入图片描述
没什么线索,放入PE里查看,是个32位的程序
在这里插入图片描述
放入32位ida里面分析伪代码:

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v3; // [esp+17h] [ebp-35h]
  int v4; // [esp+30h] [ebp-1Ch]
  int v5; // [esp+34h] [ebp-18h]
  signed int v6; // [esp+38h] [ebp-14h]
  int i; // [esp+3Ch] [ebp-10h]
  int v8; // [esp+40h] [ebp-Ch]

  __main();
  v4 = 0;
  v5 = 0;
  qmemcpy(&v3, _data_start__, 0x19u);
  while ( 1 )
  {
    puts("you can choose one action to execute");
    puts("1 up");
    puts("2 down");
    puts("3 left");
    printf("4 right\n:");
    scanf("%d", &v6);
    if ( v6 == 2 )
    {
      ++v4;
    }
    else if ( v6 > 2 )
    {
      if ( v6 == 3 )
      {
        --v5;
      }
      else
      {
        if ( v6 != 4 )
LABEL_13:
          exit(1);
        ++v5;
      }
    }
    else
    {
      if ( v6 != 1 )
        goto LABEL_13;
      --v4;
    }
    for ( i = 0; i <= 1; ++i )
    {
      if ( *(&v4 + i) < 0 || *(&v4 + i) > 4 )
        exit(1);
    }
    if ( *((_BYTE *)&v8 + 5 * v4 + v5 - 41) == 49 )
      exit(1);
    if ( *((_BYTE *)&v8 + 5 * v4 + v5 - 41) == 35 )
    {
      puts("\nok, the order you enter is the flag!");
      exit(0);
    }
  }
}

经过分析发现是一个5*5的迷宫,迷宫如图所示:
在这里插入图片描述
通过输入1234来控制上下左右
可以看出 1 为墙壁, # 为出口,那么 * 就是入口了
在这里插入图片描述

答案揭晓

通过走迷宫得出:flag{222441144222}

第十题(1分)

在这里插入图片描述
附件是一个二进制文件,放入PE里查看,是一个64位的elf文件:
在这里插入图片描述
放入64位ida里面分析伪代码:

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  char v4; // [rsp+Fh] [rbp-1h]

  while ( 1 )
  {
    while ( 1 )
    {
      printf("Welcome to CTF game!\nPlease input d/D to start or input q/Q to quit this program: ", argv, envp);
      v4 = getchar();
      if ( v4 != 100 && v4 != 68 )
        break;
      Decry();
    }
    if ( v4 == 113 || v4 == 81 )
      Exit();
    puts("Input fault format!");
    v3 = getchar();
    putchar(v3);
  }
}

简单分析后的知要想继续就得输入d/D,然后进入函数 Decry()

unsigned __int64 Decry()
{
  char v1; // [rsp+Fh] [rbp-51h]
  int v2; // [rsp+10h] [rbp-50h]
  int v3; // [rsp+14h] [rbp-4Ch]
  int i; // [rsp+18h] [rbp-48h]
  int v5; // [rsp+1Ch] [rbp-44h]
  char src[8]; // [rsp+20h] [rbp-40h]
  __int64 v7; // [rsp+28h] [rbp-38h]
  int v8; // [rsp+30h] [rbp-30h]
  __int64 v9; // [rsp+40h] [rbp-20h]
  __int64 v10; // [rsp+48h] [rbp-18h]
  int v11; // [rsp+50h] [rbp-10h]
  unsigned __int64 v12; // [rsp+58h] [rbp-8h]

  v12 = __readfsqword(0x28u);
  *(_QWORD *)src = 357761762382LL;
  v7 = 0LL;
  v8 = 0;
  v9 = 512969957736LL;
  v10 = 0LL;
  v11 = 0;
  text = (char *)join(key3, &v9);
  strcpy(key, key1);
  strcat(key, src);
  v2 = 0;
  v3 = 0;
  getchar();
  v5 = strlen(key);
  for ( i = 0; i < v5; ++i )
  {
    if ( key[v3 % v5] > 64 && key[v3 % v5] <= 90 )
      key[i] = key[v3 % v5] + 32;
    ++v3;
  }
  printf("Please input your flag:", src);
  while ( 1 )
  {
    v1 = getchar();
    if ( v1 == 10 )
      break;
    if ( v1 == 32 )
    {
      ++v2;
    }
    else
    {
      if ( v1 <= 96 || v1 > 122 )
      {
        if ( v1 > 64 && v1 <= 90 )
          str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
      }
      else
      {
        str2[v2] = (v1 - 39 - key[v3++ % v5] + 97) % 26 + 97;
      }
      if ( !(v3 % v5) )
        putchar(32);
      ++v2;
    }
  }
  if ( !strcmp(text, str2) )
    puts("Congratulation!\n");
  else
    puts("Try again!\n");
  return __readfsqword(0x28u) ^ v12;
}

大致意思是先用算法算出钥匙key的值,然后带入后面的flag加密算法

答案解析

用脚本跑出出key的值,接着用key的值逆向算法加小爆破解出flag的值,python3脚本如下:

key=['A', 'D', 'S', 'F', 'K', 'N', 'D', 'C', 'L', 'S']
v3=0
v5=10
for i in range(10):
    if ord(key[v3%v5])>64 and ord(key[v3%v5])<=90:
        key[i]=ord(key[v3%v5])+32
        v3+=1
        key[i]=chr(key[i])
print('key',key)
text=['k', 'i', 'l', 'l', 's', 'h', 'a', 'd', 'o', 'w']
flag1=['0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
flag='flag{'
v3=0
for x in range(4):
    for w in range(10):
        v1=(ord(text[w])-97)+26*x+ord(key[v3%10])-58
        if (v1>65 and v1<=90):
            flag1[w]=chr(v1)
        v3 += 1
for d in range(10):
    flag+=flag1[d]
print(flag+'}')

在这里插入图片描述
flag{KLDQCUDFZO}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值