鹏程实验室邀请赛

简介:部分题的wp,总结一些没见过的一些知识点吧。

1.base64+32

文件是个html文件,打开

LJWXQ2C2PFKTGULKLEZE6RCKNBNEIRTMJRKFC6SZGJGXITSEIEZFUQZRNBNGUQLZJRKFE2SOPJNGYWTKLEYFUV2JGJHFGVJTKJAT2PI=

先进行base32解码,在进行base64解码,得到

flag%7B6682ad1e-43cc-406d-af02-4c76ef64eb65%7D

看起有点像,开始不知道URL编码,交flag一直不对,试了几次,终于对了。

flag{6682ad1e-43cc-406d-af02-4c76ef64eb65}

URL编码表https://blog.csdn.net/sinat_34439107/article/details/78242584

2.cpp

IDA打开,找到关键代码

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rax
  __int64 v4; // rax
  _BYTE *v5; // rbx
  char v6; // r12
  __int64 v7; // rax
  int v9; // [rsp+Ch] [rbp-E4h]
  __int64 v10[2]; // [rsp+10h] [rbp-E0h] BYREF
  __int64 v11[2]; // [rsp+20h] [rbp-D0h] BYREF
  char v12[32]; // [rsp+30h] [rbp-C0h] BYREF
  char v13[32]; // [rsp+50h] [rbp-A0h] BYREF
  char v14[32]; // [rsp+70h] [rbp-80h] BYREF
  int v15[18]; // [rsp+90h] [rbp-60h]
  unsigned __int64 v16; // [rsp+D8h] [rbp-18h]

  v16 = __readfsqword(0x28u);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v13, argv, envp);
  v3 = std::operator<<<std::char_traits<char>>(&std::cout, "Please input flag:");
  std::ostream::operator<<(v3, &std::endl<char,std::char_traits<char>>);
  std::operator>><char>(&std::cin, v13);//输入的flag,v13
  if ( std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length(v13) != 16 )//长度为16
  {
    v4 = std::operator<<<std::char_traits<char>>(&std::cout, "length error");
    std::ostream::operator<<(v4, &std::endl<char,std::char_traits<char>>);
    exit(0);
  }
  v15[0] = 18;
  v15[1] = 19;
  v15[2] = 20;
  v15[3] = 22;
  v15[4] = 18;
  v15[5] = 17;
  v15[6] = 18;
  v15[7] = 19;
  v15[8] = 20;
  v15[9] = 22;
  v15[10] = 18;
  v15[11] = 17;
  v15[12] = 17;
  v15[13] = 18;
  v15[14] = 18;
  v15[15] = 24;
  std::allocator<int>::allocator(v10);
  LODWORD(v11[0]) = 0;
  std::vector<int>::vector(v12, 16LL, v11, v10);
  std::allocator<int>::~allocator(v10);
  v9 = 0;//相当于循环里面的i。
  __gnu_cxx::__normal_iterator<int *,std::vector<int>>::__normal_iterator(v10);
  v10[0] = std::vector<int>::begin(v12);
  while ( 1 )
  {
    v11[0] = std::vector<int>::end(v12);
    if ( !(unsigned __int8)__gnu_cxx::operator!=<int *,std::vector<int>>(v10, v11) )
      break;
    *(_DWORD *)__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator*(v10) = v15[v9];
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::substr(v14, v13, v9, 1LL);//这里是c++里面的复制字符串函数,相当于strcmp,将v13给了v14。
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](v14, 0LL);
    v5 = (_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](v13, v9);
    v6 = *(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](v14, 0LL);
    *v5 = v6 ^ *(_DWORD *)__gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator*(v10);//这里就是那个异或,相当于flag[i]=flag[i]^v15[i]
    ++v9;
    std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v14);
    __gnu_cxx::__normal_iterator<int *,std::vector<int>>::operator++(v10);
  }
  if ( (unsigned int)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::compare(
                       (__int64)v13,
                       (__int64)&enc[abi:cxx11]) )//这里是比较函数,只不过好像不能直接看到加密后的内容。
    v7 = std::operator<<<std::char_traits<char>>(&std::cout, "try again :(");
  else
    v7 = std::operator<<<std::char_traits<char>>(&std::cout, "Good,you got it,flag is flag{your input}");
  std::ostream::operator<<(v7, &std::endl<char,std::char_traits<char>>);
  std::vector<int>::~vector(v12);
  std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v13);
  return 0;
}

就是一个异或,然后最后那个密文好像要通过动调得到,但是在ida的字符串窗口也可以找到(只是可能你不知道那是密文)。然后写脚本。

#include<stdio.h> 

int main(void)
{
    int flag[16]={'#', '!', 0x27, '"', 0x27, 0x27, '%', '+', '-', '&', '#', '#','"', '&', 0x27, '.'};
    int i;
    int v15[16]={18,19,20,22,18,17,18,19,20,22,18,17,17,18,18,24};

    for(i=0;i<16;i++)
    {
        flag[i]=flag[i]^v15[i];
        printf("%c",flag[i]);
    }
}

得到
flag{12334567890123456}

3.crypto

这道题主要考了rc4,以后会整理一篇关于一些加密算法的博客,解这道题可以参考https://baike.baidu.com/item/RC4/3454548?fr=aladdin,我认为这道题就用的里面的代码。

ida打开,找到关键代码

先用python进行base64解码。

import base64
url = "x1H/EcYUm448LIIVkU3p1hKzOQHegw=="
str_url = base64.b64decode(url)
print(str_url)

得到’\xc7Q\xff\x11\xc6\x14\x9b\x8e<,\x82\x15\x91M\xe9\xd6\x12\xb39\x01\xde\x83’

然后在rc4解密

#include<stdio.h>
#include<string.h>
#include <wchar.h>
typedef unsigned longULONG;

/*初始化函数*/
void rc4_init(unsigned char*s, unsigned char*key, unsigned long Len)
{
    int i = 0, j = 0;
    char k[256] = { 0 };
    unsigned char tmp = 0;
    for (i = 0; i<256; i++)
    {
        s[i] = i;
        k[i] = key[i%Len];
    }
    for (i = 0; i<256; i++)
    {
        j = (j + s[i] + k[i]) % 256;
        tmp = s[i];
        s[i] = s[j];//交换s[i]和s[j]
        s[j] = tmp;
    }
}

/*加解密*/
void rc4_crypt(unsigned char*s, unsigned char*Data, unsigned long Len)
{
    int i = 0, j = 0, t = 0;
    unsigned long k = 0;
    unsigned char tmp;
    for (k = 0; k<Len; k++)
    {
        i = (i + 1) % 256;
        j = (j + s[i]) % 256;
        tmp = s[i];
        s[i] = s[j];//交换s[x]和s[y]
        s[j] = tmp;
        t = (s[i] + s[j]) % 256;
        Data[k] ^= s[t];
    }
}

int main()
{
    unsigned char s[256] = { 0 }, s2[256] = { 0 };//S-box
    char key[256] ="i_am_3_key";
    char pData[256] = {'\xc7', 'Q', '\xff', '\x11', '\xc6', '\x14', '\x9b', '\x8e', '<', ',', '\x82', '\x15', '\x91', 'M', '\xe9', '\xd6', '\x12', '\xb3', '9', '\x01', '\xde', '\x83'};
    unsigned long len = strlen(pData);
    int i;

    printf("pData=%s\n", pData);
    printf("key=%s,length=%d\n\n", key, strlen(key));
    rc4_init(s, (unsigned char*)key, strlen(key));//已经完成了初始化
    printf("\n");
    for (i = 0; i<256; i++)//用s2[i]暂时保留经过初始化的s[i],很重要的!!!
    {
        s2[i] = s[i];
    }
    rc4_crypt(s2, (unsigned char*)pData, len);//解密
    printf("pData=%s\n\n", pData);
    return 0;
}

得到

flag{rc4_is_very_easy}

4.apk

jeb打开,就是一个简单的异或,写出脚本

#include<stdio.h>

int main(void)
{
    int a[42]={0x71, 0x7B, 0x76, 0x70, 108, 0x20, 34, 46, 0x71, 0x71, 0x74, 0x72, 0x75, 58, 33, 34, 0x74, 0x73, 58, 35, 46, 34, 33, 58, 46, 0x74, 0x71, 39, 58, 35, 0x71, 0x20, 0x75, 37, 0x72, 36, 0x74, 38, 0x74, 36, 36, 106}; 
    int i;

    for(i=0;i<42;i++)
    {
        a[i]=a[i]^23;
        printf("%c",a[i]);
    }
 } 

得到

flag{759ffceb-65cd-4956-9cf0-4f7b2e3c1c33}

5.apk2

文件下载下来用jeb打开,然后搜索字符串,找到关键代码

然后去找密文

得到name=enc,然后去resources/values/sting.xml里面找到enc的值,这里有两种方法,第一种是直接在jeb里面找,第二种是用apktool将apk解包,在解包文件中找,这里只写第一种方法。

第二种方法,就给两个链接,https://blog.csdn.net/qq_27292113/article/details/79931268https://www.cnblogs.com/QKSword/p/8184997.html

java -jar .\apktool_2.3.0.jar d .\app-debug.apk -o QKSword//解包命令

注意需要先将enc倒序得到ZmxhZ3s1MmU2YjBiZi00OGY4LTQ5ZDItOTBmYi04NWI0ZWIxOGFlNTR9,然后base64解密得到

flag{52e6b0bf-48f8-49d2-90fb-85b4eb18ae54}