7.25 逆向where is your flag

我们先在IDA里面打开这道题,打开之后使用shift+fn+f12查看字符串内容界面;
这里写图片描述
首先我们点击where is your flag这个,按f5键就会出来逆向的伪C语言程序了。
int __cdecl main(int argc, const char **argv, const char **envp)
{
if ( argc <= 1 )
{
puts("where is your flag?");
}
else if ( (unsigned int)test(argv[1], argv, envp) )
{
puts("you got it!");
}
else
{
puts("try again!");
}
return 0;
}
我们可以看到如果我们满足了else if ( (unsigned int)test(argv[1], argv, envp) 这个条件,我们就可以得到我们想要的flag,所以我们要着重分析这个。我们直接进入test函数,

_BOOL8 __fastcall test(__int64 a1)
{
  signed int i; // [rsp+1Ch] [rbp-24h]
  __int64 s2; // [rsp+20h] [rbp-20h]
  __int64 v4; // [rsp+28h] [rbp-18h]#int64占八个字节
  __int16 v5; // [rsp+30h] [rbp-10h]#int16占两个字节
  char v6; // [rsp+32h] [rbp-Eh]#char在Java语言中是占两个字节
  unsigned __int64 v7; // [rsp+38h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  s2 = 0x3929531D01070A00LL;
  v4 = 0x391257391F150703LL;
  v5 = 0x150F;
  v6 = 0x1B;
  if ( strlen((const char *)a1) != 19 )
    return 0LL;
  for ( i = 0; i <= 18; ++i )
    *((_BYTE *)&s2 + i) ^= 0x66u;
  return !memcmp((const void *)a1, &s2, 5uLL)
      && *(_BYTE *)(a1 + 18) == v6
      && *(_BYTE *)(a1 + 7) == *(_BYTE *)(a1 + 10)
      && *(_BYTE *)(a1 + 10) == *(_BYTE *)(a1 + 13)
      && *(char *)(a1 + 13) == SHIBYTE(s2) - 49
      && !memcmp((const void *)(a1 + 5), (char *)&v4 + 5, 2uLL)
      && !memcmp((const void *)(a1 + 8), &v5, 2uLL)
      && !memcmp((const void *)(a1 + 11), (char *)&s2 + 5, 2uLL)
      && !memcmp((const void *)(a1 + 14), &v4, 4uLL);
}
if ( strlen((const char *)a1) != 19 )
    return 0LL;
  for ( i = 0; i <= 18; ++i )
    *((_BYTE *)&s2 + i) ^= 0x66u;

由以上代码得知,a1的长度应该为19,然后我们需要对s2进行亦或处理。
a^=b的意思是与b亦或后将值赋给a,接下来要进行亦或处理。

  s2 = 0x3929531D01070A00LL;
  v4 = 0x391257391F150703LL;
  v5 = 0x150F;
  v6 = 0x1B;

由于s2、v4、v5和v6的地址是相连的,所以当从s2的起始地址开始进行19个字节的异或处理时,v4、v5和v6中的数值也会被处理。由于s2占据了多个字节,在存储的过程中,一定存在着先分配的字节放在高地址还是低地址的问题。在s2中先分配的字节应该是放在了低地址处。
低地址、高地址:内存地址可以对应十六进制的数值,值大的为高地址,否则为低地址;
对s2,v4,v5中的元素按顺序写出,应为:
s2 = 0x00,0x0A,0x07,0x01,0x1D,0x53,0x29,0x39;
v4 = 0x03,0x07,0x15,0x1F,0x39,0x57,0x12,0x39;
v5 = 0x0F,0x15;
v6 = 0x1B;

用python语言表示为:

s2=[0x00,0x0a,0x07,0x01,0x1d,0x53,0x29,0x39,0x03,0x07,0x15,0x1f,0x39,0x57,0x12,0x39,0x0f,0x15,0x1b]
for i in range(0,len(s2)):
   s2[i]=chr(s2[i]^0x66)
 return !memcmp((const void *)a1, &s2, 5uLL)
      && *(_BYTE *)(a1 + 18) == v6
      && *(_BYTE *)(a1 + 7) == *(_BYTE *)(a1 + 10)
      && *(_BYTE *)(a1 + 10) == *(_BYTE *)(a1 + 13)
      && *(char *)(a1 + 13) == SHIBYTE(s2) - 49
      && !memcmp((const void *)(a1 + 5), (char *)&v4 + 5, 2uLL)
      && !memcmp((const void *)(a1 + 8), &v5, 2uLL)
      && !memcmp((const void *)(a1 + 11), (char *)&s2 + 5, 2uLL)
      && !memcmp((const void *)(a1 + 14), &v4, 4uLL);

对于下面这些代码,需要按个分析
(1)return !memcmp((const void )a1, &s2, 5uLL)我们要想得到flag要使得test函数成立,这个return要返回1,因为有个‘’,所以我们要使得memcmp((const void )a1, &s2, 5uLL)最后返回0。
**memcmp函数的用法:
****s1,s2为字符串时候
memcmp(s1,s2,1)就是比较s1和s2的第一个字节的ascII码值
memcmp(s1,s2,n)就是比较s1和s2的前n个字节的ascII码值;
**返回值
如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str2 小于 str1。**
如果返回值 = 0,则表示 str1 等于 str2。**
所以我们要使得a1的前五个字节与s2相等,即

flag[0:5]=s2[0:5]#[:]语法[起始:结束],切片选取的区间属于左闭右开,即即从"起始"位开始,到"结束"位的前一位结束。

(2) && *(_BYTE *)(a1 + 18) == v6
&& *(_BYTE *)(a1 + 7) == *(_BYTE *)(a1 + 10)
&& *(_BYTE *)(a1 + 10) == *(_BYTE *)(a1 + 13)
&& *(char *)(a1 + 13) == SHIBYTE(s2) - 49

用python语言表示:

flag[18]=s2[18]
flag[7]=s2[10]
flag[10]=s2[13]
s2[13]=chr(ord(s2[7]-49))

(3)&& !memcmp((const void *)(a1 + 5), (char *)&v4 + 5, 2uLL)
&& !memcmp((const void *)(a1 + 8), &v5, 2uLL)
&& !memcmp((const void *)(a1 + 11), (char *)&s2 + 5, 2uLL)
&& !memcmp((const void *)(a1 + 14), &v4, 4uLL);

用python表示:

  flag[5:7]=s2[13:15]
  flag[8:10]=s2[16:18]
  flag[11:13]=s2[5:7]
  flag[14:18]=s2[8:12]

总代码:

flag=[0 for i in range(19)]#flag=[0]*19
s2=[0x00,0x0a,0x07,0x01,0x1d,0x53,0x29,0x39,0x03,0x07,0x15,0x1f,0x39,0x57,0x12,0x39,0x0f,0x15,0x1b]

for i in range(19):
    s2[i]=chr(s2[i]^0x66)
flag[0:5]=s2[0:5]
flag[18]=s2[18]
**flag[13]=chr(ord(s2[7])-49)
flag[10]=flag[13]
flag[7]=flag[10]**#先将flag[13]的值赋给了flag[10],然后又将flag[10]的值赋给了flag[7],顺序不能反
flag[5:7]=s2[13:15]
flag[8:10]=s2[16:18]
flag[11:13]=s2[5:7]
flag[14:18]=s2[8:12]
a=" "
for i in range(len(s2)):
    a+=flag[i]
print (a)
 flag{1t.is.5O.easy}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值