攻防世界re 新手区wp

文章目录

  • 攻防世界re 新手区wp
    • re1
    • game
    • hello,ctf
    • open-source
    • simple-unpack
    • logmein
    • insanity
    • no-strings-attached
    • CSAW2013Reversing2
    • gitit
    • python-trade
    • maze

攻防世界re 新手区wp

这个几天没有之前忙了,现在有时间整理一下之前做的攻防世界新手区的题目,记录一下学习过程,也复习一下
https://adworld.xctf.org.cn/

re1

方法一:
下载附件,die查壳,无壳,
载入ida查看攻防世界re 新手区wp_第1张图片简单的明文比较,将比较过后的结果赋给v5,v5就是flag
查看上面两个字符串
攻防世界re 新手区wp_第2张图片一串数字按r转换为字符串如上,然后写出脚本即可得到flag
DUTCTF{We1c0met0DUTCTF}

str1='0tem0c1eW{FTCTUD'[::-1]
str2='}FTCTUD'[::-1]
print(str1+str2)

这里要注意数据大小端的储存方式,这里形成的字符串时逆序。

方法二:载入od中文搜索查看字符串,发现flag就在字符串里面,简单粗暴
攻防世界re 新手区wp_第3张图片

game

下载附件
die查壳,无壳

方法一:
载入od动态调试,攻防世界re 新手区wp_第4张图片
攻防世界re 新手区wp_第5张图片注意记住上面的072E940是判断正确函数的入口点,然后现在的思路就很清晰了,就是找到判断我们输入是否正确的函数,将其跳转到判断正确的函数入口点来,也就是072E940地址。
接下来就是找输入的地方了,慢慢调试,找到%d
攻防世界re 新手区wp_第6张图片设置个断点,单步运行,找到跳转的指令攻防世界re 新手区wp_第7张图片将其改为jle long 0072e940,然后运行得到flag
方法二:
载入ida分析,shift+f12查看字符串,这样方便快速定位关键函数
攻防世界re 新手区wp_第8张图片
这个函数就是关键函数,f5查看伪代码攻防世界re 新手区wp_第9张图片攻防世界re 新手区wp_第10张图片
函数有三部分构成
第一部分输出游戏的规则信息,第二部分就是游戏的运行部分,第三部分就是判断我们输入的n是否正确,
如果正确,然后跳到下面的sub_458054函数,猜测打印出flag,进入该函数看看


  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的函数,py写出脚本,运行得到flag
zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}

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]
str = ''
for i in range(0, 56):
    b[0 + i] ^= a[0 + i]
    b[0 + i] ^= 0x13
    str = str + chr(b[i]);
print(str)

方法三,这是网上大佬的另外一种思路

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 )

这里判断出我们需要将这八个数组的值都变为1,也就是8盏灯都闭合。
打开sub_4576D6函数
攻防世界re 新手区wp_第11张图片分析得到按键与电路闭合的关系:

按1--闭合1,2,8
按8--闭合1,7,8
按i(除1,8)--闭合i-1,i,i+1

附上大佬c+汇编爆破代码

#include 
#include 

using namespace std;

#define for(a,b,c) for(int a = b; a < c; ++a)
#define N 8

vector<int> flag(8,-1);

void func(int *arr){
    for(i,0,N){
        int n = arr[i];
        if(n == 0){
            flag[0] *= -1;
            flag[1] *= -1;
            flag[7] *= -1;
        }else{
            if(n == 7){
                flag[0] *= -1;
                flag[6] *= -1;
                flag[7] *= -1;
            }else{
                flag[n] *= -1;
                flag[n-1] *= -1;
                flag[n+1] *= -1;
            }
        }
    }
}

bool Judge(){
    for(i,0,8)
    if(flag[i] == -1)
    return false;
    
    return true;
}

int main(void)
{
    int array[N] = {0};
    for(i,0,8)
    for(j,0,8)
    for(k,0,8)
    for(m,0,8)
    for(n,0,8)
    for(p,0,8)
    for(q,0,8)
    for(t,0,8){
        array[0] = i;
        array[1] = j;
        array[2] = k;
        array[3] = m;
        array[4] = n;
        array[5] = p;
        array[6] = q;
        array[7] = t;
        func(array);
        if(Judge()){
            cout << "success:" << i+1 << j+1 << k+1 << m+1 << n+1 << p+1 << q+1 << t+1 << endl;
            system("PAUSE");
        }else{
            for(x,0,8)
            fill(flag.begin(), flag.end(), -1);
        } 
    }
    
    cout << "over!";
    
    system("PAUSE");
    return 0;
}

hello,ctf

die查壳无壳,载入ida查看攻防世界re 新手区wp_第12张图片函数很简单,就是将我们输入的值进行16进制转换过后与v13进行比较,也就是说将v13的十六进制数转换位字符串就是flag

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

后记:这道题学习了sprintf这个函数,这个函数处理字符串可谓强大。
头文件:stdio.h
声明:int sprintf(char *string, char *format [,argument,…]);
功能:把格式化的数据写入某个字符串缓冲区。
例子1:

int main( void )
 
{
   char  buffer[200], s[] = "computer", c = 'l';
   int   i = 35, j;
   float fp = 1.7320534f;
   // 格式化并打印各种数据到buffer
   j  = sprintf( buffer,    "   String:    %s\n", s ); // C4996
   j += sprintf( buffer + j, "   Character: %c\n", c ); // C4996
   j += sprintf( buffer + j, "   Integer:   %d\n", i ); // C4996
   j += sprintf( buffer + j, "   Real:      %f\n", fp );// C4996
    
   printf( "Output:\n%s\ncharacter count = %d\n", buffer, j );
      return 0;
}
>>>输出结果
>Output:
String: computer
Character: l
Integer: 35
Real: 1.732053
character count = 79

格式化数字字符串sprintf 最常见的应用之一莫过于把整数打印到字符串中

//把整数123 打印成一个字符串保存在s 中。
sprintf(s, "%d", 123); //产生"123"
sprintf(s, "%4d%4d", 123, 4567); //产生:" 1234567"
sprintf(s, "%-4d%4d", 123, 4567); //产生:"123 4567"

也可以按照16 进制打印:

sprintf(s, "%8x", 4567); //小写16 进制,宽度占8 个位置,右对齐
sprintf(s, "%-8X", 4568); //大写16 进制,宽度占8 个位置,左对齐

打印16 进制内容时,如果想要一种左边补0 的等宽格式,在表示宽度的数字前面加个0 就可以了。

sprintf(s, "%08X", 4567); //产生:"000011D7"

控制浮点数打印格式,默认保留小数点后6 位数字

sprintf(s, "%f", 3.1415926); //产生"3.141593"

但有时我们希望自己控制打印的宽度和小数位数,这时就应该使用:”%m.nf”格式,其中m 表示打印的宽度,n 表示小数点后的位数。比如:

sprintf(s, "%10.3f", 3.1415626); //产生:" 3.142"
sprintf(s, "%-10.3f", 3.1415626); //产生:"3.142 "
sprintf(s, "%.3f", 3.1415626); //不指定总宽度,产生:"3.142"

连接字符串

char buf[60]={0};
char*who="I";
char*whom="CSDN";
sprintf(buf,"%slove%s.",who,whom);
printf("%s",buf);
//输出结果:"IloveCSDN."

open-source

下载附件,附件是一份c语言源码,这就很简单了

 1 #include <stdio.h>
 2 #include <string.h>
 3 
 4 int main(int argc, char *argv[]) {
 5     if (argc != 4) {
 6         printf("what?\n");
 7         exit(1);
 8     }
 9 
10     unsigned int first = atoi(argv[1]);
11     if (first != 0xcafe) {
12         printf("you are wrong, sorry.\n");
13         exit(2);
14     }
15 
16     unsigned int second = atoi(argv[2]);
17     if (second % 5 == 3 || second % 17 != 8) {
18         printf("ha, you won't get it!\n");
19         exit(3);
20     }
21 
22     if (strcmp("h4cky0u", argv[3])) {
23         printf("so close, dude!\n");
24         exit(4);
25     }
26 
27     printf("Brr wrrr grr\n");
28 
29     unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;
30 
31     printf("Get your key: ");
32     printf("%x\n", hash);
33     
34     return 0;
35 }

第29行计算flag,第32行代码输出十六进制形式
三部分组成,三个数组运算
第一部分:

if (first != 0xcafe) {
        printf("you are wrong, sorry.\n");
        exit(2);
    }
first=0xcafe

第二部分:

if (second % 5 == 3 || second % 17 != 8) {
        printf("ha, you won't get it!\n");
        exit(3);
    }
second=25

第三部分:

if (strcmp("h4cky0u", argv[3])) {
        printf("so close, dude!\n");
        exit(4);
    }
相等strcmp返回0,退出if条件,那argv[3]=“h4cky0u”

综上,用C语言写出脚本

#include 
#include 

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

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

    unsigned int hash = first * 31337 + (second % 17) * 11 + strlen(argv[3]) - 1615810207;
    printf("%x\n", hash);
  	
  	return 0;
}

simple-unpack

下载附件elf文件,die查壳,64位,upx的壳,linux下upx -d 脱壳
攻防世界re 新手区wp_第13张图片如何脱壳:网上去下载upx-3.95-amd64_linux.tar.xz,解压缩到linux一个文件夹,然后将要脱壳的文件也扔进这个文件夹,然后就再该文件夹下打开终端,再./upx -d “要脱壳的文件名”(注意没有“”哈)!
载入ida64,找到main函数,就出现的这个flag就是真的flag
攻防世界re 新手区wp_第14张图片

logmein

die查壳,无壳,载入ida
攻防世界re 新手区wp_第15张图片
这里要注意大小端序的问题,接下来写出py脚本

v7 = 'ebmarah'[::-1]
v8 = ":\"AL_RT^L*.?+6/46"
for i in range(len(v8)):
	print(chr(ord(v7[i % 7]) ^ ord(v8[i])),end='')

遗留问题:什么时候该大小端序转换?

insanity

查壳无壳32位,载入ida,shift+f12查找字符串,直接出来flag,当真如题目所说,来个简单的签到题。。。
攻防世界re 新手区wp_第16张图片

no-strings-attached

查壳,无壳,32位
攻防世界re 新手区wp_第17张图片这是关键函数攻防世界re 新手区wp_第18张图片
处理部分在这个加密函数decrypt里面攻防世界re 新手区wp_第19张图片攻防世界re 新手区wp_第20张图片
idapy脚本将传入decrypt() 的两个参数打印出来,注意舍去最后的0

addr1=0x8048a90 
addr2=0x8048aa8
a2=[]
dest=[]
for i  in range(6):
    a2.append(Dword(addr1+4*i))
for j in range(38):
	dest.append(Dword(addr2+4*j))
print(a2)
print(dest)

攻防世界re 新手区wp_第21张图片然后py写出脚本

a2 = [5121, 5122, 5123, 5124, 5125]
dest = [5178, 5174, 5175, 5179, 5248, 5242, 5233, 5240, 5219, 5222, 5235, 5223, 5218, 5221, 5235, 5216, 5227, 5233, 5240, 5226, 5235, 5232, 5220, 5240, 5230, 5232, 5232, 5220, 5232, 5220, 5230, 5243, 5238, 5240, 5226, 5235, 5243, 5248]
i = j = 0
while i < 38:
	j = 0
	while j <5 and i < 38:
		dest[i] -= a2[j]
		i += 1
		j += 1
flag = ''
for i in range(38):
	flag+= (chr(dest[i]))

print(flag)

CSAW2013Reversing2

查壳无壳,载入ida
攻防世界re 新手区wp_第22张图片
发现就两个函数,一个调用窗口的messageboxa函数一个判断是否被调试的函数,推断不乱码的函数是sub_401000函数,这里面有真正的flag
攻防世界re 新手区wp_第23张图片点进去看,一个加密函数,但是上面的流程图显示,这个函数应该没有被执行,
现在载入od看看,中文搜索字符串flag,找到关键地点,
攻防世界re 新手区wp_第24张图片果不其然,sub_401000函数被跳过去了,弹窗,然后显示乱码,我们需要执行sub_401000函数,所以将其跳转到该函数前一步,005E109B处,然后,还需要一个跳转调出messagebox,所以还要将下面的跳转跳转到第二个flag位置,因为flag是在lpMem + 1位置处弹出来的。
此时eax当中和栈中也如期出现了flag攻防世界re 新手区wp_第25张图片
攻防世界re 新手区wp_第26张图片

gitit

查壳无壳,载入ida分析
攻防世界re 新手区wp_第27张图片上面部分是处理字符串得到flag,下面部分是处理文件,重点是上面部分,s和t是关键
查看s和t的值,py逆向写出脚本
攻防世界re 新手区wp_第28张图片

s = 'c61b68366edeb7bdce3c6820314b7498'
flag=''
for i in range(len(s)):
	a = -1
	if i & 1:
		a = 1
	flag += (chr(ord(s[i]) + a))
print(flag)

然后将得到在字符串用SharifCTF{}包裹得到flag

python-trade

下载附件,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
correct = 'XlNkVmtUI1MgXWBZXCFeKY+AaXNt'
a = base64.b64decode(correct)
flag = ''
for i in range(len(a)):
	x = a[i]
	x -= 16
	y = x ^ 32
	flag += chr(y)
print(flag)

nctf{d3c0mpil1n9_PyC}

maze

这个题,提示是个迷宫题,查壳无壳,ida分析
结构很复杂,f5代码很多,查找字符串
攻防世界re 新手区wp_第29张图片 ******* * **** * **** * *** # *** *** *** *********
上面这个就是迷宫了,分析伪代码得知这是一个8
8的迷宫
我们将迷宫打印出来,为了方便,我们将空格代替为o

攻防世界re 新手区wp_第30张图片
上下左右分别是.0Oo,走迷宫,用nctf{}包裹得到flag为nctf{o0oo00O000oooo…OO}

你可能感兴趣的:(攻防世界re)