攻防世界进阶Re(二)

感觉难度越来越大了,把进阶题分为几篇来写,以便查看。

0x00 reverse-box

感觉都是没有看到过的题型,看了大佬WP,还是不懂。。。先留着以后再看。
要用GDB命令脚本先放个链接如何写gdb命令脚本

0x01 IgniteMe

这道题就非常的友好了,拖进IDA。


image.png

检查输入的前四个字符为 ' EIS{ ' 最后一个为 ‘ } ’,然后进入sub_4011c0() 关键函数。
这个函数就是交换大小写,然后异或操作之后看与最后的字符串一不一样。


image.png

首先双击unk_4420B0选中,按shift+e 把它提取出来(新学的操作,好舒服啊!终于不用手动码了)。
然后就是写脚本异或回去得到v4了,在转换大小写加上 EIS{ 和 } 就是flag了。
image.png

脚本如下:

a = "GONDPHyGjPEKruv{{pj]X@rF"
xor_string = [ 0x0D, 0x13, 0x17, 0x11, 0x02, 0x01, 0x20, 0x1D, 0x0C, 0x02, 
               0x19, 0x2F, 0x17, 0x2B, 0x24, 0x1F, 0x1E, 0x16, 0x09, 0x0F, 
               0x15, 0x27, 0x13, 0x26, 0x0A, 0x2F, 0x1E, 0x1A, 0x2D, 0x0C, 
               0x22, 0x04]
s = []
flag = ''
for i in range(len(a)):
    s.append(ord(a[i])^ xor_string[i])
for i in range(len(s)):
    s[i] -= 72
    s[i] = s[i]^0x55
for i in s:
    flag += chr(i)
print(flag.lower())

0x02 srm-50

这道题感觉我是非预期解啊,都不分析什么,正解应该是用OD破解找到注册码的。我直接拖进IDA,F12找到报错的字符串,看到if判断语句,将v11[0],v11[1],v11[2],v11[3],v12,v13…………连续字符得到就是flag了。。。。。。


image.png

0x03 ReverseMe-120

拖进IDA,看到主函数感觉很简单的亚子。我们看到最后只判断了v13是否与“you_know_how_to_remove_junk_code” 一样,往上分析v13经过了sub_401000()然后与0x25异或。


image.png

跟进sub_401000(),分析不出来是什么,,,看了大佬的WP ,这是base64的解密,还是太菜了,没有看出特征。所以将“you_know_how_to_remove_junk_code” 与0x25异或后再base64加密得到flag。


image.png

0x04 CRACKME

运行exe,要调入注册码,随便输入有弹窗错误。拖进IDA,发现是MFC写的程序。参考大佬文章,MessageBoxA函数是于创建、显示并操作一个消息对话框的,所以我们找到调用MessageBoxA的函数。


image.png

跟进sub_401720 和sub_4016E0发现不了什么,继续查看他们的引用。在这里就可以猜测这两个MessageBoxA一个是显示错误弹窗一个是正确弹窗。输入的数据经过sub_401630()之后才判断对错。所以跟进sub_401630()分析。


image.png

这里看了WP有点不懂,为什么伪随机数种子一直都是1 ,伪随机数不变。继续分析 if 里面,就是每隔10个字符判断是否相等。
image.png

这里将一个很长的字符串复制给v2+96,看WP说v2就是上面的v3,这一点也有些疑惑,没有看出来。也许是this指针的原因吧。接下来这个长字符串从第二个字符开始到330位,每隔10位取出一个字符。


image.png

脚本如下:
a = ";f1K3{c5:efl21t4;1t1zaxpim9}5+?gtux;=vc9v{v7+buhU{bT=-am2q}=fh[xk{y?xrqe{?}l5-sd2-Mo+:j{9=sY[dalvpx?z3{?no{[k5ll{zjsu5[kfla+r6Zg72o0skq6cGl5cw[=d?3v9q5-vkjSv{4sqtg=f0cz{+jurjfl[tb]lrfF1;2}udhb?0g8{om:T4dh;z:oz-Dn=m=ux;o[gs9{+zqx+sq-dsxctcvykUs2oddrt43pwv:f0;njkrb9los6g0{ih?rqantfx$sslqd:rvqixr;j{?o:sn+[i[yA11;gsmr8lm0?3};+iv+Tf:4Gtv2:-20upi0]7?77=;qzx{m-W;0vtueh]ko8d?=w:fbhd{E:;19?p=k:b+}doht6wpEq-z]2qbV1}dh416qw9:xm[;ed;:ecb-0:ni-s4u2kf6]2wn45amzjrun=ofkx-=hmgo-lz;j909=rmo7xcj4le0hxs[i]-vjl[?o12:sv4upio7ma1hRy7556+57krev:hLQ+1cx65z5v5];6n=[p83;n={zm{k2p"
for i in range(1,330,10):
   print(a[i],end='')

0x05 tt3441810

这道题看不懂,以为是手动脱壳。搜了官方WP,也是一脸懵逼,这是杂项题吗?
用IDA或者notepad++打开看到十六进制数,在这里看到 ‘fl’ ,{ } 等字样,然后把一些混淆字符去掉得到flag,还得提交括号里面的内容。又看了里面自带的WP,还是学到了xxd使用。
flag{poppopret}

image.png

0x06 zorropub

先拖进IDA,分析下程序流程,题的意思很简单,主要是输入饮料的数量和饮料ID经过下面函数在计算MD5,判断其MD5是否相等。


  v15 = __readfsqword(0x28u);
  seed = 0;
  puts("Welcome to Pub Zorro!!");
  printf("Straight to the point. How many drinks you want?", a2);
  __isoc99_scanf("%d", &v5);
  if ( v5 <= 0 )
  {
    printf("You are too drunk!! Get Out!!", &v5);
    exit(-1);
  }
  printf("OK. I need details of all the drinks. Give me %d drink ids:", (unsigned int)v5);
  for ( i = 0; i < v5; ++i )
  {
    __isoc99_scanf("%d", &v6);   //循环输入饮料ID
    if ( v6 <= 16 || v6 > 0xFFFF )  //饮料ID在 [16,65535]范围内。
    {
      puts("Invalid Drink Id.");
      printf("Get Out!!", &v6);
      exit(-1);
    }
    seed ^= v6;   //随机种子
  }
  i = seed;
  v9 = 0;
  while ( i )
  {
    ++v9;
    i &= i - 1;
  }
  if ( v9 != 10 )
  {
    puts("Looks like its a dangerous combination of drinks right there.");
    puts("Get Out, you will get yourself killed");
    exit(-1);
  }
  srand(seed);
  MD5_Init((__int64)&v10);
  for ( i = 0; i <= 29; ++i )
  {
    v9 = rand() % 1000;
    sprintf(&s, "%d", v9);
    v3 = strlen(&s);
    MD5_Update((__int64)&v10, (__int64)&s, v3);
    v12[i] = v9 ^ LOBYTE(dword_6020C0[i]);   //LOBYTE()得到一个16bit数最低(最右边)那个字节
  }
  v12[i] = 0;
  MD5_Final(v11, &v10);
  for ( i = 0; i <= 15; ++i )
    sprintf(&s1[2 * i], "%02x", (unsigned __int8)v11[i]);
  if ( strcmp(s1, "5eba99aff105c9ff6a1a913e343fec67") )
  {
    puts("Try different mix, This mix is too sloppy");
    exit(-1);
  }
  return printf("\nYou choose right mix and here is your reward: The flag is nullcon{%s}\n", v12);
}

这里我们有两种思路,1.爆破MD5,2.逆向算法。
1.爆破MD5:
先根据饮料ID范围在 [16,65535],和下面check来从中筛选出符合ID的值。

 while ( i )
  {
    ++v9;
    i &= i - 1;
  }
  if ( v9 != 10 )

在使用subprocess库,(想使用pwntools的,结果没有搜到pwntools如何杀死进程的函数,看了大佬文章才知道还有subprocess的),将满足ID的数使用subprocess里的communicate()带进去试一试,看能否返回flag。
脚本如下:

#!/usr/bin/python
# -*- coding: utf-8 -*-
from subprocess import *

#这里是找出符合条件的数
a=[]
for i in range(16,65535):
    v9 = 0
    s=i
    while i:
        v9 +=1
        i &= i-1
    if v9 == 10:
        a.append(s)
#循环输入符合条件的数,爆破flag
for i in a:
    proc = Popen(['./zorro_bin'],stdin=PIPE,stdout=PIPE)
    out = proc.communicate(('1\n%s\n' % i).encode('utf-8'))[0]#这里communicate返回的是一个元组,但是元组只有一个元素,所以要加上偏移0。
    if "nullcon".encode('utf-8') in out:
      print(out)
      print(i)
image.png

2.逆向算法
这是在官方WP复制的。利用libc.so.6动态链接库得到生成的伪随机数。然后对着IDA的函数复现一遍。得到结果也是输入59306的时候正确。

import ctypes
import os
import sys
import hashlib
libsystem = ctypes.CDLL('libc.so.6')
# Extracted by hand
encryption_key = [
    0x03C8, 0x0032, 0x02CE, 0x0302, 0x007F,
    0x01B8, 0x037E, 0x0188, 0x0349, 0x027F,
    0x005E, 0x0234, 0x0354, 0x01A3, 0x0096,
    0x0340, 0x0128, 0x02FC, 0x0300, 0x028E,
    0x0126, 0x001B, 0x032A, 0x02F5, 0x015F,
    0x0368, 0x01EB, 0x0079, 0x011D, 0x024E
]
need_md5 = '5eba99aff105c9ff6a1a913e343fec67'
mc = 0
while True:
    for drink_id_count in range(17, 0xFFFE):
        mc += 1
        if mc % 1000 == 0:
            sys.stdout.write('.')
            sys.stdout.flush()
        for counter in range(5):
            input_1 = counter
            seed = 0
            drink_ids = []
            for x in range(input_1):
                drink_id = drink_id_count
                drink_ids.append(drink_id)
                if drink_id <= 16 or drink_id > 0xFFFF:
                    continue
                else:
                    seed ^= drink_id
            count = seed
            some_num = 0
            while count > 1:
                some_num += 1
                count &= (count - 1)
            if some_num != 10:
                continue
            else:
                pass
            libsystem.srand(seed)
            flag = ""
            h = hashlib.md5()
            for x in range(30):
                ran = libsystem.rand()
                rand_number = ran % 1000
                h.update("%d" % rand_number)
                flag += chr((rand_number ^ encryption_key[x])&0xFF)#LOBYTE()得到一个16bit数最低(最右边)那个字节,所以   & 0xff
            if h.hexdigest() == need_md5:
                print "\nHash -> %s" % h.hexdigest()
                print "Found it! Drinks:%d, Drink IDs:%s" % (counter, drink_ids)
                raw_input()

0x07 Reversing-x64Elf-100

IDA打开,主函数。分析得到主要逻辑函数为sub_4006FD(),非常简单的逻辑,写脚本得到flag。

signed __int64 __fastcall sub_4006FD(__int64 a1)
{
  signed int i; // [rsp+14h] [rbp-24h]
  const char *v3; // [rsp+18h] [rbp-20h]
  const char *v4; // [rsp+20h] [rbp-18h]
  const char *v5; // [rsp+28h] [rbp-10h]

  v3 = "Dufhbmf";
  v4 = "pG`imos";
  v5 = "ewUglpt";
  for ( i = 0; i <= 11; ++i )
  {
    if ( (&v3)[i % 3][2 * (i / 3)] - *(char *)(i + a1) != 1 )
      return 1LL;
  }
  return 0LL;
}
脚本如下:
arr = [
       ['D','u','f','h','b','m','f'],
       ['p','G','`','i','m','o','s'],
       ['e','w','U','g','l','p','t']
      ]
for i in range(12):
    key = arr[i%3][2*int(i/3)] 
    print(chr(ord(key)-1),end='')
    

0x08 gametime

这道题主要靠细心,先运行一下看看,在拖进IDA,分析下逻辑。这个游戏就是靠手快,刚好出现规定字符时,按一下对应字符进入下一关,越来越快,这单身一辈子也没有这手速啊。。所以拖进OD,找到些关键跳转下断点,耐心的调试耐心的调试耐心的调试耐心的调试,就出来key了。

这里总结下OD的使用:

  • 找到关键字符,在其上方第一个跳转一般为关键跳转,越过正确字符的跳转为关键跳转。
  • 在关键跳转处下断点,运行到断点时看将要跳转到哪里去,在判断是否跳转,比如有几个跳转都将向同一个地址跳转,那么这个跳转就改成不跳转,因为游戏出错有一点错误就退出,所以这里一定是指向错误的输出函数,正确的只有一条路,不可能有多个跳转指向它。
  • 遇到JMP跳转一般不要改,因为这个是无条件跳转,无论你输入的正确与否,它都将跳转。
  • 出现需要循环运行时,不用一个个的按F8,在跳转的下面一行下断点,然后F9直接运行,将会断在刚刚下断点处。
  • 边调试边看运行结果,看是否正确输出。
image.png

0x09 easyre-153

首先UPX脱壳。IDA打开,看到pipe()和fork()。
pipe函数可用于创建一个管道,以实现进程间的通信。
fork函数通过系统调用创建一个与原来进程几乎完全相同的进程,其返回值是进程号。

这里的逻辑就是输入一个进程号要与之前的进程号相等。就显示正确。
image.png
  v8 = __readgsdword(0x14u);
  pipe(pipedes);
  v5 = fork();
  if ( !v5 )
  {
    puts("\nOMG!!!! I forgot kid's id");
    write(pipedes[1], "69800876143568214356928753", 0x1Du);
    puts("Ready to exit     ");
    exit(0);
  }
  read(pipedes[0], &buf, 0x1Du);
  __isoc99_scanf("%d", &v6);
  if ( v6 == v5 )
  {
    if ( (*(_DWORD *)((_BYTE *)lol + 3) & 0xFF) == 204 )
    {
      puts(":D");
      exit(1);
    }
    printf("\nYou got the key\n ");
    lol(&buf);
  }
  wait(0);
  return 0;
}

但是这里就算输入正确,lol函数也会返回 'flag_is_not_here',所以我们需要使用IDA动态调试
去修改汇编改变跳转得到flag,之前的进程号也可以随便输然后改变后面的关键跳转即可。

image.png

得到flag,要加上RCTF。太坑了,我以为我的不是flag,看了WP才知道。
image.png

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容