2019_UNCTF BabyXor

2019_UNCTF BabyXor


1.WriteUp
2.知识点








声明一点以下可能说的不是很友好,所以如有敏感词汇请评论我,作者会改











WriteUp

下载压缩包,解压得到babyXor.exe文件,习惯步骤:exe文件用PEiD查壳

在这里插入图片描述

UPolyX v0.5 * 作为菜鸡说实话第一见这种壳,以前都是upx壳,所以先用万能脱壳工具FFI进行脱壳

在这里插入图片描述
原谅我这个新手看不懂,所以貌似是无法识别这个壳,那就只能手动脱壳
使用esp脱壳大法,这是今天的一个收获之一
将exe拖到od

在这里插入图片描述
直接调试到jmp那里

在这里插入图片描述
使用od脱壳插件

在这里插入图片描述
脱壳后形成脱壳后的exe文件
由于菜所以只能用ida进行伪代码查看,大神就直接通过od进行分析代码结构,无疑让人羡慕

int __cdecl main_0()
{
  int v0; // ST5C_4
  int v1; // ST6C_4
  char *v2; // ST68_4
  void *v3; // ST64_4
  size_t v4; // eax
  int v5; // ST60_4

  sub_4010B4((int)&unk_4395F0, "世界上最简单的Xor");
  sub_40107D(sub_40102D);
  if ( --stru_436270._cnt < 0 )
  {
    _filbuf(&stru_436270);
  }
  else
  {
    v0 = (unsigned __int8)*stru_436270._ptr;
    ++stru_436270._ptr;
  }
  v1 = sub_40108C(&unk_435DC0, 56);
  v2 = (char *)sub_401041((int)&unk_435DC0, (int)&dword_435DF8, 0x38u);
  v3 = malloc(0x64u);
  v4 = strlen(v2);
  memcpy(v3, v2, v4);
  v5 = sub_4010C3(&unk_435DC0, v2, &dword_435E30, 56);
  sub_40101E(v1, v2, v5);
  return 0;
}

根据某个大神的解题思路得到启发,看这些简单一点的代码就应该有flag答案的地方从下往上看函数,看了半天也没有发现flag的踪迹,那就先分析重要函数吧

sub_4010C3(&unk_435DC0, v2, &dword_435E30, 56);
(char *)sub_401041((int)&unk_435DC0, (int)&dword_435DF8, 0x38u);
sub_40108C(&unk_435DC0, 56);
sub_40107D(sub_40102D);
sub_4010B4((int)&unk_4395F0, "世界上最简单的Xor");

找到这些重要的函数先不着急,先看传参,并找出其关联

sub_40108C(&unk_435DC0, 56);

访问&unk_435DC0

在这里插入图片描述
显然是一个数组,不过在此之间,和我一样的菜鸡注意了,怎么找值
1.找类型,此处类型为db,及占4个字节,及是以四个字节为媒介进行分开
2.看地址,上图是一个地址一个地址进行分开
3.看端序,及所谓小端序(高到低)和大端序(低到高)
又上面3个要点可以得到
435DC0=[0x66,0x6d,0x63,0x64,0x7f,0x37,0x35,0x30,0x30,0x6b,0x3a,0x3c,0x3b,0x20]

(char *)sub_401041((int)&unk_435DC0, (int)&dword_435DF8, 56u);

访问&dword_435DF8

在这里插入图片描述
435DF8=[0x37,0x6f,0x38,0x62,0x36,0x7c,0x37,0x33,0x34,0x76,0x33,0x62,0x64,0x7a]

sub_4010C3(&unk_435DC0, v2, &dword_435E30, 56);

访问dword_435E30
得到
435E30=[0x1a,0,0,0x51,0x5,0x11,0x54,0x56,0x55,0x59,0x1d,0x9,0x5d,0x12,0,0]
关联:

 v2 = (char *)sub_401041((int)&unk_435DC0, (int)&dword_435DF8, 56u);
sub_4010C3(&unk_435DC0, v2, &dword_435E30, 56);

可以得到v2的值对sub_4010C3有影响,但是sub_40108C(&unk_435DC0, 56);没有与其有任何关联,所以软柿子肯定要捏一捏,在这之前先可以判断

sub_40107D(sub_40102D);
sub_4010B4((int)&unk_4395F0, "世界上最简单的Xor");

这二个函数应该是打印窗口所以暂时可以不要管

//sub_40108C(&unk_435DC0, 56);
char *__cdecl sub_401190(int a1, unsigned int a2)
{
  char *v3; // [esp+4Ch] [ebp-Ch]
  signed int i; // [esp+54h] [ebp-4h]

  v3 = (char *)malloc(a2 >> 2);
  for ( i = 0; i < (signed int)(a2 >> 2); ++i )
    sprintf(&v3[i], "%c", i ^ *(_DWORD *)(a1 + 4 * i));//435DC0的值与i进行异或得到的结果赋值给v3这个字符串数组
  return v3;
}

我们先脚本输出结果一下

在这里插入图片描述
???flag出现了,而且是断片的,这时就瞬间明白了三个函数可能是进行拼凑flag

//sub_401041((int)&unk_435DC0, (int)&dword_435DF8, 0x38u);
char *__cdecl sub_401240(int a1, int a2, size_t a3)
{
  signed int i; // [esp+4Ch] [ebp-Ch]
  char *v5; // [esp+50h] [ebp-8h]

  v5 = (char *)malloc(a3);//初始化字符串v5
  sprintf(v5, "%c", *(_DWORD *)a2);//将435DF8[0]=v5[0]
  for ( i = 1; i < (signed int)(a3 >> 2); ++i )
    sprintf(&v5[i], "%c", *(_DWORD *)(a1 + 4 * i) ^ *(_DWORD *)(a2 + 4 * i) ^ *(_DWORD *)(a1 + 4 * i - 4));//v5[i]=435DC0[i]^435DF8[i]^435DC0[i-1]
  return v5;
}

得到v5=[55, 100, 54, 101, 45, 52, 53, 54, 52, 45, 98, 100, 99, 97]

//sub_4010C3(&unk_435DC0, v2, &dword_435E30, 56);
char *__cdecl sub_401320(int a1, int a2, int a3, unsigned int a4)
{
  int i; // [esp+4Ch] [ebp-10h]
  char *v6; // [esp+50h] [ebp-Ch]
  char *v7; // [esp+54h] [ebp-8h]

  v7 = (char *)malloc(a4 - 1);
  v6 = (char *)malloc(4 * a4 - 1);
  for ( i = 0; i < (signed int)((a4 >> 2) - 1); ++i )
  {
sprintf(&v6[i], "%c", *(_DWORD *)(a3 + 4 * i + 4) ^ *(char *)(i + a2));//这里的a2等于上面的v5,所以v6[i]=435E30[i+1]^v5[i]
    sprintf(&v7[i], "%c", i ^ v6[i]);
  }
  sprintf(&byte_439558, "%c", dword_435E30 ^ dword_435DF8);
  strcat(&byte_439558, v7);
  return &byte_439558;
}

Python-writeup:

a1=[0x66,0x6d,0x63,0x64,0x7f,0x37,0x35,0x30,0x30,0x6b,0x3a,0x3c,0x3b,0x20]
a2=[0x37,0x6f,0x38,0x62,0x36,0x7c,0x37,0x33,0x34,0x76,0x33,0x62,0x64,0x7a]
a3=[0x1a,0,0,0x51,0x5,0x11,0x54,0x56,0x55,0x59,0x1d,0x9,0x5d,0x12,0,0]
s=''
s2=[]
for x in range(0,14):
    s+=chr(x ^ a1[x])
print(s)
s+=chr(a2[0])
s2.append(a2[0])
for  x in range(1,14):
    s+=chr(a1[x]^a2[x]^a1[x-1])
    s2.append(a1[x]^a2[x]^a1[x-1])
print(s2)
s+=chr(a3[0]^a2[0])
for x in range(0,13):
    s+=chr(x^(a3[x+1]^s2[x]))

print(s)

最终得到flag{2378b077-7d6e-4564-bdca-7eec8eede9a2}















知识点

esp脱壳大法

条件:当按f8后esp变红即可用esp脱壳大法

在这里插入图片描述
使用教程
1.先用先用dd命令转到堆栈刚才esp中的内容指的位置,即dd 0019ff64。随即在该处下硬件断点,如图:

在这里插入图片描述
2.按F9运行,然后我们F8单步走,到了有大跳转时不要再按F8了(这是向上跳转的),我们必须跳过去,因为接下来就有可能是程序的OEP领空
在这里插入图片描述
在这里插入图片描述









  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值