跟着大佬学RE(三)

crackMe

!isalnum(a1i)

string.isalnum()

是 python 中检查字符串是否全是字母或者数字,是返回true,否则false

刷新文件流缓冲区

应该和 flag 没有什么关系,继续往下看

嗯,我把所有 jz 改成了 jnz ,不对是直接 nop 掉 那个 if 语句

nop掉了,F5 显示代码过大,已经改那个 MAX_FUNSIZE 了啊!

只能先不改,看的时候注意一下分析吧

得到 v17:dbappsec

接下来就是要得到 byte_416050 数组

找一个比较合适的位置(有特殊(xor,add,sub之类的)指令位置)下断点

得到 ecx 每次循环的值:

0x7e,0x98,0xc9,0x95,0x10,0x6d,0xf3,0x67 就八个

得到的 byte 数组不对,啊!

都是用 OD 调的,我也去算了(用的ida)

撕,用的 x32dbg 调的,隐不隐藏调试器都得到了正确数组

那那个反调试是搞什么?只是防止静态分析吗?

python 复制代码
#include <bits/stdc++.h>
using namespace std;
int a[] = {0x2A, 0xD7, 0x92, 0xE9, 0x53, 0xE2, 0xC4, 0xCD};
string s = "dbappsec";
int main() {
  for (int i = 0; i < 8; i++) {
  	int num = (int)s[i]; 
  	int ans = num ^ (int)a[i];
  	cout << hex << ans;
  }
  return 0;
}

中间那个 Encode(生成Rc4表) 函数好像也没什么用

并且这个题开了重定位

FlareOn4IgniteMe

GetInput 函数:

CheckInput:

sub_401000 函数返回一个 key 用于下面异或,该值可以静态分析,也可以动态调试,exe 没有开重定位。逻辑都很简单。

MRCTF2020Xor

ida:analyse failed

这个错一般是 ida 无法正确识别 函数参数个数函数调用约定 导致的。尤其是调用如 printf、scanf 这些参数个数可变的函数函数时,ida 会出现这样的错误

需要看 output window,通过 log 信息知道是哪句调用分析失败了,当然弹窗也给地址了

双击进去看看,按 F5 ,再回到 main 函数 可以 F5 了,如果还不行就要人工干预,将光标放在函数头的位置按 'Y' 强行修改参数个数或参数类型

然后就非常简单了

GKCTF2020BabyDriver

Windows 10 Driver x64

flag{} 中为 32 位小写。

那最后再写吧

WUSTCTF2020Cr0ssfun

藏在一个个函数里,主要想学学使用 sublime 的正则替换功能

ctrl+n 新建文件

嗯,抽时间学一下正则表达式

2019红帽杯xx

主体逻辑都在 main 函数里了

中间一大坨不知道在干嘛

只能倒着看了,硬着头皮啃

python 复制代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rbx
  __int64 v4; // rax
  __int128 *v5; // rax
  __int64 v6; // r11
  __int128 *v7; // r14
  int v8; // edi
  __int128 *v9; // rsi
  char v10; // r10
  int v11; // edx
  __int64 v12; // r8
  unsigned __int64 v13; // rcx
  __int64 v14; // rcx
  unsigned __int64 v15; // rax
  unsigned __int64 i; // rax
  __int64 v17; // rax
  size_t v18; // rsi
  _BYTE *v19; // rbx
  _BYTE *v20; // r9
  int v21; // r11d
  char *v22; // r8
  __int64 v23; // rcx
  char v24; // al
  __int64 v25; // r9
  __int64 v26; // rdx
  __int64 v27; // rax
  size_t Size; // [rsp+20h] [rbp-48h] BYREF
  __int128 v30; // [rsp+28h] [rbp-40h] BYREF
  int v31; // [rsp+38h] [rbp-30h]
  int v32; // [rsp+3Ch] [rbp-2Ch]
  int Code[4]; // [rsp+40h] [rbp-28h] BYREF
  int v34; // [rsp+50h] [rbp-18h]

  *(_OWORD *)Code = 0i64;
  v34 = 0;
  scanf(std::cin, argv, Code);
  v3 = -1i64;
  v4 = -1i64;
  do
    ++v4;
  while ( *((_BYTE *)Code + v4) );              // strlen(Code)=19
  if ( v4 != 19 )
  {
    print(std::cout, "error\n");
    _exit((int)Code);
  }
  v5 = (__int128 *)operator new(5ui64);
  v6 = *(_QWORD *)&::Code;                      // qwertyuiopasdfghjklzxcvbnm1234567890
  v7 = v5;
  v8 = 0;
  v9 = v5;
  do
  {
    v10 = *((_BYTE *)v9 + (char *)Code - (char *)v5);
    v11 = 0;
    *(_BYTE *)v9 = v10;
    v12 = 0i64;
    v13 = -1i64;
    do
      ++v13;
    while ( *(_BYTE *)(v6 + v13) );
    if ( v13 )
    {
      do
      {
        if ( v10 == *(_BYTE *)(v6 + v12) )
          break;
        ++v11;
        ++v12;
      }
      while ( v11 < v13 );
    }
    v14 = -1i64;
    do
      ++v14;
    while ( *(_BYTE *)(v6 + v14) );
    if ( v11 == v14 )
      _exit(v6);
    v9 = (__int128 *)((char *)v9 + 1);
  }
  while ( (char *)v9 - (char *)v5 < 4 );
  *((_BYTE *)v5 + 4) = 0;
  do
    ++v3;
  while ( *((_BYTE *)Code + v3) );
  v15 = 0i64;
  v30 = *v7;
  while ( *((_BYTE *)&v30 + v15) )
  {
    if ( !*((_BYTE *)&v30 + v15 + 1) )
    {
      ++v15;
      break;
    }
    if ( !*((_BYTE *)&v30 + v15 + 2) )
    {
      v15 += 2i64;
      break;
    }
    if ( !*((_BYTE *)&v30 + v15 + 3) )
    {
      v15 += 3i64;
      break;
    }
    v15 += 4i64;
    if ( v15 >= 0x10 )
      break;
  }
  for ( i = v15 + 1; i < 0x10; ++i )
    *((_BYTE *)&v30 + i) = 0;
  v17 = sub_140001AB0(Code, v3, &v30, &Size);
  v18 = Size;
  v19 = (_BYTE *)v17;
  v20 = operator new(Size);
  v21 = 1;
  *v20 = v19[2];
  v22 = v20 + 1;
  v20[1] = *v19;
  v20[2] = v19[3];
  v20[3] = v19[1];
  v20[4] = v19[6];
  v20[5] = v19[4];
  v20[6] = v19[7];
  v20[7] = v19[5];
  v20[8] = v19[10];
  v20[9] = v19[8];
  v20[10] = v19[11];
  v20[11] = v19[9];
  v20[12] = v19[14];
  v20[13] = v19[12];
  v20[14] = v19[15];
  v20[15] = v19[13];
  v20[16] = v19[18];
  v20[17] = v19[16];
  v20[18] = v19[19];
  v20[19] = v19[17];
  v20[20] = v19[22];
  v20[21] = v19[20];
  v20[22] = v19[23];
  for ( v20[23] = v19[21]; v21 < v18; ++v22 )
  {
    v23 = 0i64;
    if ( v21 / 3 > 0 )
    {
      v24 = *v22;
      do
      {
        v24 ^= v20[v23++];
        *v22 = v24;
      }
      while ( v23 < v21 / 3 );
    }
    ++v21;
  }
  *(_QWORD *)&v30 = 0xC0953A7C6B40BCCEui64;
  v25 = v20 - (_BYTE *)&v30;
  *((_QWORD *)&v30 + 1) = 0x3502F79120209BEFi64;
  v26 = 0i64;
  v31 = -939386845;
  v32 = -95004953;
  do
  {
    if ( *((_BYTE *)&v30 + v26) != *((_BYTE *)&v30 + v26 + v25) )
      _exit(v8 * v8);
    ++v8;
    ++v26;
  }
  while ( v26 < 24 );
  v27 = print(std::cout, "You win!");
  std::ostream::operator<<(v27, sub_1400017F0);
  return 0;
}
python 复制代码
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "encode.h"
int main()
{
    int i,j,data[] = { 188, 165, 206, 64, 244, 178, 178, 231, 169, 18, 157, 18, 174, 16, 200, 91, 61, 215, 6, 29, 220, 112, 248, 220 };
    for (i = 1; i <= 6; i++)//导出加密的数据,将其转换为十六进制并用小端序来表示
    {
        printf("0x");
        for (j = i * 4 - 1; j > (i - 1) * 4 - 1; j--)
            printf("%x", data[j]);
        printf(",");
    }
    printf("\n0x");
    int key[] = { 'f','l','a','g' };//导出密钥,将其转换为十六进制并用小端序来表示
    for (i = 3; i >= 0; i--)
        printf("%x", key[i]);
    printf(",");
    for (i = 0; i < 3; i++)//密钥为4个32位的数,1个字符4bit,4个字符为32bit,还差3个32bit的数
        printf("0x0,");
}
//0x40cea5bc,0xe7b2b2f4,0x129d12a9,0x5bc810ae,0x1d6d73d,0xdcf870dc,
//0x67616c66,0x0,0x0,0x0,

感觉自己写脚本能力还是不行,只能先 copy 师傅的了,之后还是要多练。

python 复制代码
data0 = "CEBC406B7C3A95C0EF9B202091F70235231802C8E75656FA"
data=[]
for i in range(0,len(data0),2):
    data.append(int((data0[i]+data0[i+1]),16)) #十六进制字符串变成数据
print(data)
for i in range(len(data)-1,-1,-1):
    for j in range(i//3):
        data[i]^=data[j]
order=[2,0,3,1,6,4,7,5,10,8,11,9,14,12,15,13,18,16,19,17,22,20,23,21]#还原顺序
enc=[1]*24
for i in range(24):
    enc[order[i]]=data[i]
print(enc)
# [206, 188, 64, 107, 124, 58, 149, 192, 239, 155, 32, 32, 145, 247, 2, 53, 35, 24, 2, 200, 231, 86, 86, 250]
# [188, 165, 206, 64, 244, 178, 178, 231, 169, 18, 157, 18, 174, 16, 200, 91, 61, 215, 6, 29, 220, 112, 248, 220]
python 复制代码
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include "encode.h"
int main()
{
#if 0
    uint32_t enc[6] = { (unsigned int)0x40cea5bc,(unsigned int)0xe7b2b2f4,(unsigned int)0x129d12a9,(unsigned int)0x5bc810ae,(unsigned int)0x1d06d73d,(unsigned int)0xdcf870dc };
    int n = -6;
    uint32_t const key[4] = { (unsigned int)0x67616c66,(unsigned int)0x0,(unsigned int)0x0,(unsigned int)0x0 };
    btea(enc, n, key);
    for (int i = 0; i < 6; i++)
        printf("%x", enc[i]);
#endif
    char string[] = "67616c665858437b646e615f742b2b5f7d6165";
    int i = 1,j=0;
    for (;i<6;i++)
    {
        for (j = 0; j < 8; j += 2)
        {
            if (j == 0 && i == 5)
                continue;
            printf("%c%c", string[i * 8 - j - 2], string[i * 8 - j - 1]);
        }
    }
}
//666c61677b4358585f616e645f2b2b7465617d 

gBUUCTF re 2019红帽杯xx WP - 简书

相关推荐
古城小栈6 小时前
为啥说:训练用BF16,推理用FP16
人工智能·算法·机器学习
KaMeidebaby6 小时前
卡梅德生物技术快报|蛋白 N 端测序在重组贻贝融合蛋白表征中的应用,解决原核表达序列偏移工艺难题
前端·人工智能·物联网·算法·百度
Turbo正则7 小时前
群论在AI中的应用概述
人工智能·算法·抽象代数
ysa0510307 小时前
【并查集】判环
c++·笔记·算法
Jerry7 小时前
KeetCode 44. 开发商购买土地
算法
Jerry7 小时前
KeetCode 58. 区间和
算法
Jerry8 小时前
LeetCode 209. 长度最小的子数组
算法
彦为君9 小时前
算法思维与经典智力题
java·前端·redis·算法
智能优化与强化学习9 小时前
Gym(Gymnasium)仿真环境详解(二):环境简介、入门算法、调参要点、核心挑战
算法·强化学习·gym·零基础入门·算法评估
mxwin9 小时前
Unity Shader exp 函数的算法与渲染应用
算法·unity·游戏引擎·shader