MP3文件隐写之Copyright位

最近在帮人做CTF的时候遇到一道有意思的题目,记录一下思维过程。

题目整个只有一个MP3文件的附件。下载

0x01

首先观察16进制数据,没有发现异常,只有一个PNG图片作为封面图,提取PNG图片观察图片的16进制数据,也没有发现任何异常。

0x02

观察到Comment tag中有一个 163 key(Don’t modify)

经查询资料得知是网易云MP3里的元数据。AES-128-ECB加密,用密码 #14ljk_!\]&0U<'( 解码,得到一个Json字符串,观察并没有发现任何有用信息。

0x03

使用Audacity加载,观察波形图和频谱图,没有发现异常。

0x04

猜测使用Mp3Stego加密,但是没有密码,无法解密。使用Mp3Stego测试了几个常用密码以后放弃。

0x05

正在一筹莫展没有思路的时候,发现MP3格式的帧数据中,有一个uint32 private_bit,可以作为私有数据的标记位。帧头具体格式为:

typedef FrameHeader

{

unsigned int sync:11;                        //同步信息

unsigned int version:2;                      //版本

unsigned int layer: 2;                           //层

unsigned int error protection:1;           // CRC校验

unsigned int bitrate_index:4;              //位率

unsigned int sampling_frequency:2;         //采样频率

unsigned int padding:1;                    //帧长调节

unsigned int private:1;                       //保留字

unsigned int mode:2;                         //声道模式

unsigned int mode extension:2;        //扩充模式

unsigned int copyright:1;                           // 版权

unsigned int original:1;                      //原版标志

unsigned int emphasis:2;                  //强调模式

}

曾经也有题目是使用private_bit来隐藏Flag。但是翻看了几帧发现private_bit位都是0,似乎并没有存储数据。但是在翻看的时候发现,uint32 copyright这一位似乎内藏玄机,这一位在相邻几帧的数据有0有1,查询得知这是版权位,通常不会出现不同帧有0有1的情况。

于是决定将copyright位的数据提取出来看看。

0x06

在提取的过程中发现一个问题。该MP3文件每一帧的长度不固定,有的是414H,有的是415H,一开始完全没有找到规律。网上相关题目和private位隐写数据的示例,也都是固定帧长度的。只好另外想办法。

翻看资料得知帧长度的变化和padding填充位有关。

帧长度是压缩时每一帧的长度,包括帧头的4个字节。它将填充的空位也计算在内。Layer 1的一个空位长4字节,Layer 2和Layer 3的空位是1字节。当读取MPEG文件时必须计算该值以便找到相邻的帧。注意:因为有填充和比特率变换,帧长度可能变化

观察本文件得知如果padding位为1,帧长度就是415H,padding位为0,帧长度就是414H。

查询得知第一帧的起始位置为984484,又因为帧头为4个字符,padding_bit位于第三个字符的倒数第二位,而copyright位于第四个字符的倒数第四位。所以从984486开始查找,向后读取一个字节提取padding_bit,再向后读取一个字节提取copyright。

故写出一下python代码进行copyright位的提取。

# coding:utf-8
import re
import binascii

n = 984486  # 起始位置
result = ''
file = open('2.mp3', 'rb')
# 提取
while n < 12658083:  # 结束位置
    file.seek(n, 0)
    head = file.read(1)
    padding = '{:08b}'.format(ord(head))[-2]

    file.seek(n+1, 0)
    file_read_result = file.read(1)
    result += '{:08b}'.format(ord(file_read_result))[-4]

    n += 1045 if padding == "1" else 1044
# 拼接
flag = ''
textArr = re.findall('.{'+str(8)+'}', result)
for i in textArr:
    flag = flag + chr(int(i, 2)).strip('\n')
print(flag)

执行代码得到 flag{b3d7bed5-e8da-4d9c-848c-e5d332d63bcd}

成功找到Flag,收工。

给Pico-Pi-I.MX7D安装Debian系统

手上有个闲置的PicoPI-I.MX7D,使用的是NXP的MCIMX7D7DVM10SC芯片,看了一下是ARM v7架构的,拥有512M内存和1G主频。虽然很鸡肋,但是好歹是个板子,不用又觉得浪费,于是想装一个Debian Linux上去跑跑小脚本用。

查阅了一圈资料发现,想用这货跑起debian需要自己编译内核外加使用u-boot来启动。
说干就干

1. BootLoader的写入

安装一些交叉编译的依赖库和软件

ARM Cross Compiler: GCC

1
2
3
wget -c https://releases.linaro.org/components/toolchain/binaries/6.5-2018.12/arm-linux-gnueabihf/gcc-linaro-6.5.0-2018.12-x86_64_arm-linux-gnueabihf.tar.xz
tar xf gcc-linaro-6.5.0-2018.12-x86_64_arm-linux-gnueabihf.tar.xz
export CC=`pwd`/gcc-linaro-6.5.0-2018.12-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
1
${CC}gcc --version

接下来编译U-boot

1
2
3
4
5
git clone -b v2019.07-rc4 https://github.com/u-boot/u-boot --depth=1
cd u-boot/
make ARCH=arm CROSS_COMPILE=${CC} distclean
make ARCH=arm CROSS_COMPILE=${CC} pico-pi-imx7d_defconfig
make ARCH=arm CROSS_COMPILE=${CC}

这样我们就拥有了一个适用于imx7d的U-boot。

想把BootLoader下载到板子上,需要用官方的 imx_usb_loader

连接板子的Console串口和type-c数据接口,从Github下载 imx_usb_loader。设置跳线到Download模式

1
2
3
git clone https://github.com/boundarydevices/imx_usb_loader
cd imx_usb_loader/
make
1
2
lsusb | grep Freescale
Bus 00x Device 00y: ID 15a2:0076 Freescale Semiconductor, Inc

使用imx_usb_loader加载SPL和uboot进系统

1
2
sudo ~/imx_usb_loader/imx_usb u-boot/SPL
sudo ~/imx_usb_loader/imx_usb u-boot/u-boot-dtb.img

这样系统就能从U-boot启动了。

1
2
3
4
5
6
7
Loading Environment from MMC... OK
In: serial
Out: serial
Err: serial
Net: FEC0
Hit any key to stop autoboot: 0
=>

在U-boot里设置一些参数以便启动dfu-agent

1
2
3
4
5
=> env default -f -a
=> saveenv

=> mmc partconf 0 0 7 0
=> dfu 0 mmc 0

这样就可以使用dfu-util写入u-boot到板子的eMMC存储了

1
2
sudo dfu-util -D u-boot/SPL -a spl
sudo dfu-util -R -D u-boot/u-boot-dtb.img -a u-boot

接下来就可以把板子从Download模式恢复为eMMC启动模式

重启以后板子会自动启动到U-boot,这时候在串口可以捕捉到u-boot,并且启用挂载外置存储模式,以便往eMMC里写入系统。

1
2
3
4
5
6
7
Loading Environment from MMC... OK
In: serial
Out: serial
Err: serial
Net: FEC0
Hit any key to stop autoboot: 0
=> ums 0 mmc 0

此时电脑上应该已经可以看到USB外接存储

1
2
lsusb | grep Netchip
Bus 00x Device 00y: ID 0525:a4a5 Netchip Technology, Inc. Pocketbook Pro 903

2. 系统的内核编译和写入

Linux Kernel
1
2
3
git clone https://github.com/RobertCNelson/armv7-lpae-multiplatform
cd armv7-lpae-multiplatform/
./build_kernel.sh

这里要耗费大量时间来编译内核,以及缺少各种依赖库需要安装,大概三四个小时的时间。

RootFS

首先选择系统,这里我选择的是Debian 10,当然也可以使用Ubuntu 20

Debian 10

1
2
3
4
wget -c https://rcn-ee.com/rootfs/eewiki/minfs/debian-10.4-minimal-armhf-2020-05-10.tar.xz
sha256sum debian-10.4-minimal-armhf-2020-05-10.tar.xz
cd598e42850cbef87602bf15ee343abfbf0d8c6ba81028c741672b5f24263534 debian-10.4-minimal-armhf-2020-05-10.tar.xz
tar xf debian-10.4-minimal-armhf-2020-05-10.tar.xz

Ubuntu 20.04 LTS

1
2
3
4
wget -c https://rcn-ee.com/rootfs/eewiki/minfs/ubuntu-20.04-minimal-armhf-2020-05-10.tar.xz
sha256sum ubuntu-20.04-minimal-armhf-2020-05-10.tar.xz
de0177ac9259fdbcc626ee239f4258b64070c0921dbc38c45fab6925a5becaa1 ubuntu-20.04-minimal-armhf-2020-05-10.tar.xz
tar xf ubuntu-20.04-minimal-armhf-2020-05-10.tar.xz

使用lsblk找到外置存储,我的是/dev/sdb1,并且进行清零

1
2
export DISK=/dev/sdb
sudo dd if=/dev/zero of=${DISK} bs=1M count=10

再次安装BootLoader

1
2
sudo dd if=./u-boot/SPL of=${DISK} seek=1 bs=1k
sudo dd if=./u-boot/u-boot-dtb.img of=${DISK} seek=69 bs=1k

创建分区

1
2
3
sudo sfdisk ${DISK} <<-__EOF__
1M,,L,*
__EOF__

格式化并挂载分区

1
2
3
sudo mkfs.ext4 -L rootfs ${DISK}1
sudo mkdir -p /media/rootfs/
sudo mount ${DISK}1 /media/rootfs/

首先写入rootfs

1
2
3
4
sudo tar xfvp ./*-*-*-armhf-*/armhf-rootfs-*.tar -C /media/rootfs/
sync
sudo chown root:root /media/rootfs/
sudo chmod 755 /media/rootfs/

然后找到编译完成的内核版本,如kernel_version=5.X.Y-Z

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export kernel_version=5.X.Y-Z

sudo mkdir -p /media/rootfs/boot/extlinux/
sudo sh -c "echo 'label Linux ${kernel_version}' > /media/rootfs/boot/extlinux/extlinux.conf"
sudo sh -c "echo ' kernel /boot/vmlinuz-${kernel_version}' >> /media/rootfs/boot/extlinux/extlinux.conf"
sudo sh -c "echo ' append root=/dev/mmcblk2p1 ro rootfstype=ext4 rootwait quiet' >> /media/rootfs/boot/extlinux/extlinux.conf"
sudo sh -c "echo ' fdtdir /boot/dtbs/${kernel_version}/' >> /media/rootfs/boot/extlinux/extlinux.conf"

sudo cp -v ./armv7-lpae-multiplatform/deploy/${kernel_version}.zImage /media/rootfs/boot/vmlinuz-${kernel_version}

sudo mkdir -p /media/rootfs/boot/dtbs/${kernel_version}/
sudo tar xfv ./armv7-lpae-multiplatform/deploy/${kernel_version}-dtbs.tar.gz -C /media/rootfs/boot/dtbs/${kernel_version}/

sudo tar xfv ./armv7-lpae-multiplatform/deploy/${kernel_version}-modules.tar.gz -C /media/rootfs/

sudo sh -c "echo '/dev/mmcblk2p1 / auto errors=remount-ro 0 1' >> /media/rootfs/etc/fstab"

最后写入完成重启即可。

1
2
sync
sudo umount /media/rootfs

串口Console端

1
2
3
4
5
6
7
8
9
10
Loading Environment from MMC... OK
In: serial
Out: serial
Err: serial
Net: FEC0
Hit any key to stop autoboot: 0
=> ums 0 mmc 0
UMS: LUN 0, dev0, hwpart 0, section 0x0, count 0x720000
Ctrl+C to exit ...
=> reset

重启后就会自动进入Debian了

参考资料:

https://developer.android.com/things/hardware/imx7d

https://www.nxp.com/part/MCIMX7D7DVM10SC#/

https://www.digikey.com/eewiki/display/linuxonarm/PICO-PI-IMX7

骷髅峡谷(nuc6i7kyk)安装黑苹果(macOS Mojave 10.14.3)

一、前言

其实很久以前就给骷髅峡谷装过10.13版本的黑苹果+WIN10双系统,并且成功更新到Mojave。后来因为用的少又格式化掉了。去年用了一年的MacBook Pro以后,已经熟悉了苹果系统,并且基本工作都在macOS下完成了,遂又萌生了把骷髅峡谷装成苹果系统的想法。

黑苹果背后的基础知识我就不过多介绍了,可以在国内外各种论坛上了解,既然这次要搞,就要做到极致,目标是安装最新版的macOS系统,并且把能驱动的所有硬件都正常驱动起来,尽量完美使用骷髅峡谷的所有功能和最高效率。

二、准备

准备工作,需要的东西只是一个8G以上的U盘而已,USB3.0的为佳,因为速度会快很多。

安装黑苹果的步骤大同小异,因为这次是全盘格式化全新安装,所以我直接选择原版安装盘,使用原版安装包的磁盘管理来格式化全盘。

截止到写这篇文章为止,最新版的macOS是Mojave版本10.14.3 (18D109),使用手头的MacBook Pro直接在应用商店搜索Mojave就可以下载安装包。

下载完成后,这里因为图省事,直接使用了UniBeast来制作安装盘。这是全球最大的黑苹果论坛tonymacx86上的人开发的一款快速制作安装盘的工具,其实原理大同小异,不管MBR还是GPT分区表,首先把U盘格式化为两个区,其中EFI分区可以用FAT32或者其他格式,然后把安装包放在另一个区,并且做好引导记录,把Clover安装到EFI分区里,并且放好最小依赖的一些kext和config,安装盘就制作好了。

三、设置

这里稍微说一下我的配置,骷髅峡谷CPU是i7 6770HQ,内存我装的16G单条,SSD是SanDisk的256G非NVME接口。外接一台苹果的Apple LED Cinema Display,通过DP接口连接。

通过各方面查资料,得知我的配置没有什么和macOS不兼容的,需要调节的只是骷髅峡谷本身的一些硬件的开关。遂安心。

接下来进行一些基本BIOS设置,来把不兼容的地方修改掉。

  • Power->Secondary Power Settings, “Wake on LAN from S4/S5”, 设置成 “Stay Off”
  • Devices->Video, “IGD Minimum Memory” 设置为 64mb
  • Devices->Video, “IGD Aperture Size” 设置为 256mb
  • Boot->Secure Boot, “Secure Boot” 设置为 disabled
  • Security->Security Features, “Execute Disable Bit” 设置为 enabled.
  • Security->Security Features, “VT-d” 设置为 disabled

这里说一下骷髅峡谷的无线网卡芯片是苹果系统不支持的,所以目前没有办法驱动,可以关掉。但是蓝牙是可用的。

四、安装

插入安装U盘,开机,按F12选择从U盘启动,选择安装macOS,进入安装界面。选择磁盘工具,把整个硬盘格式化为APFS格式(Mojave只支持装在APFS分区格式上),回去选择安装,一路下一步,安装完毕自动重启。

至此系统安装完毕。

这时候安装完的macOS只是在硬盘上,因为骷髅峡谷不是苹果电脑,没法直接启动苹果系统,所以需要第三方启动器来进行引导。这时候我们就要请出Clover,关于这个启动器的资料可以上网查找,反正很强就是了。

介于刚才我们的U盘安装盘上已经装了这玩意,所以还是可以通过插入U盘来选择U盘启动,这时候Clover里多了一些选择,其中有一个preboot还是啥的可以引导进入硬盘里的苹果系统。继续执行安装过程。包括选择时区,设置用户名密码之类的,直到正式安装完毕

五、启动

再次重启,从U盘启动。我们终于看到了Boot from macOS选项。标志着macOS已经安装完毕到硬盘了。但是这只是神坑的刚刚开始。

这时候选择Boot from macOS,基本是进不去的。通过-v来看输出的log,有各种问题,需要对症下药,这里给出一个基本完美的解决方案,大致不会出现什么问题。

把U盘插到另一个电脑上,挂载EFI分区,做一下修改。

把调整完毕以后的clover启动盘插上,开机,U盘启动,选择Boot from macOS(最好还是-v看看log)。不出意外的话应该可以进入系统了。如果还是不行,需要看看-v输出的log,解决对应的error,有问题也可以和我交流。

最后需要把U盘里调好的可以启动macOS的Clover安装到硬盘的EFI分区,步骤和安装U盘Clover的差不多,如果你是UniBeast做的U盘,那你需要下载一个 https://github.com/RehabMan/Clover 的release并且安装。然后复制U盘Clover的相应文件到EFI分区即可了。

做完这步以后拔掉U盘重启,应该也可以使用硬盘的Clover引导进入macOS了。

六、调优

这时候应该可以正常启动进入macOS了,其实到这里,已经可以正常使用了。大部分硬件已经正常工作,可能性能不是最好或者部分硬件罢工罢了。如果不想折腾,或者只是体验,到这里就可以了。

如果要继续折腾可以继续看下去,但是调优这玩意是无止境的,每一个硬件都能折腾好几天,这里选择采用国外大神已经调节好的一些参数,加上部分需要自己调节的。

首先安装依赖,进入终端输入

xcode-select --install

安装完毕以后开始clone大神的git并使用

mkdir ~/Projects
cd ~/Projects
git clone https://github.com/RehabMan/Intel-NUC-DSDT-Patch nuc.git
cd ~/Projects/nuc.git
./download.sh
./install_downloads.sh
make
make install_nuc6sc

这样会自动编译DSDT/SSDT并且复制到EFI分区。

针对nuc的电源管理,执行

sudo pmset -a hibernatemode 0
sudo rm /var/vm/sleepimage
sudo mkdir /var/vm/sleepimage

最后使用文件夹里的config.plist

cp config_nuc6_sc.plist /Volumes/EFI/EFI/Clover/config.plist

这样调优就基本完成了,后续我又碰到了声音方面的问题和USB3.0不识别和掉速的问题。需要自己通过maciASL和各种kext注入的方法来解决。比较麻烦,后续如果有时间再写。

七、参考

https://www.tonymacx86.com/threads/guide-intel-skylake-nuc6-and-skull-canyon-using-clover-uefi-nuc6i5syk-nuc6i7kyk-etc.261708/

https://www.tonymacx86.com/threads/guide-booting-the-os-x-installer-on-laptops-with-clover.148093/

https://www.tonymacx86.com/resources/categories/tonymacx86-downloads.3/

用POKER改造的年轻人的第一把GH60

有一个Poker升级版的键盘,因为不支持自定义键位被我强行刷机刷成砖了。拆开看过是nuc123sd4ae0的MCU。

MCU

去网上查了各种资料,试过了各种方法,根据nuvoton官方的文档,ISP模式拉低管脚电位可以进入,试过以后也进不去,强行用Jlink调试SWD也不行。ikbc这块做的太差了,可能这种量产的键盘就是故意让你无法刷固件吧。

调试

既然都这样了,只好换主板。因为想使用60%键盘,又有很强的自定义配列需求,只好做一把GH60来用,关于GH60请自行查阅资料。

在淘宝上买了一块修改版的XD64板子,因为是熟人推荐,看起来也还不错。只需148块钱,支持60-64键的多种轴位排布和几乎兼容90%的外壳,比satan版本的GH60良心多了。

轴还是采用之前的POKER的茶轴,那么第一步就是拆轴了。把轴从之前的POKER主板上拆下来。这可是个艰巨的工作。一个一个引脚用电烙铁加热以后用吸锡器吸走焊锡。然后拔下来。整整搞了4个小时。

拆完以后的样子

等了两天,新主板终于到了。先打开看一下。为了赶潮流买了type-c的接口版本。

正面
背面

新主板到手当然是先上电用镊子挨个测试轴位的触发是否正常。

测试

接下来就是准备焊接轴上去了,来一张全部原材料的图。

原材料

茶轴特写。cherry原厂的轴质量杠杠的。

轴

轴一个一个插到定位板上。

定位板

又经过一个小时的焊接,焊接完成以后的正面和背面。

正面
背面

好久不焊东西,手生,焊点也没有那么完美了。不过没有虚焊,焊接质量还是可以保证的。

然后装上外壳
外壳

装上键帽(有钱了一定买套好看的键帽)

键帽

一套用POKER的原料和GH60的主板混合的手工制作的60%键盘就重生了。按键感觉完美。

最后上一张工作台的照片

桌面

接下来就是刷配列了,其实很简单有空再写。

迁移Jira的数据库到Mysql

前言

买了Jira Software Server自用也有一段时间了,之前安装的时候为了图省事,采用了内置的H2数据库,用了这么久,一直提醒我作为生产环境需要换成Mysql数据库,终于闲下来可以换一下。

开工

按照官方的步骤

1、首先备份数据。这个很简单,在后台就可以备份。

2、然后安装Mysql的JDBC驱动

To copy the MySQL JDBC driver to your application server:

Get the MySQL driver:
If you are installing Jira, download the recommended MySQL driver JDBC Connector/J 5.1 from https://dev.mysql.com/downloads/connector/j/ 
You can download either the .tar.gz or the .zip file by selecting the 'Platform Independent' option. Extract the jar for the driver (e.g. mysql-connector-java-5.x.x-bin.jar) from the archive.

Restart Jira / Jira service.

这里遇到了一个问题,Mysql官方下载地址 https://dev.mysql.com/downloads/connector/j/ 进去以后下载到的是Connector/J 8.0.11,而这个版本是不能在JIRA使用的,会报错。
这里一定要点Looking for previous GA versions下载老版本,我用的是5.1.46终于可以正常使用。
安装完毕后重启JIRA

3、使用官方配置工具迁移

Using the Jira configuration tool — Use this method, if you have an existing Jira instance. Your settings will be saved to the dbconfig.xml file in your Jira home directory.

这个工具默认是在/opt/atlassian/jira/里的,但是当我打开运行的时候产生了报错,说我JAVA版本不对,可是我明明JIRA都可以运行,怎么到了你这里连个工具都运行不了了呢。
查了一下资料原来是openJDK是不认的,必须是官方OracleJDK才行,因为这两个JDK的version输出不一样,要么改tools代码,要么换个JDK。我选择换JDK,毕竟OpenJDK后面还不知道有啥坑,还是用Oracle官方的吧。

使用工具一步步配置好数据库连接以后,启动Jira,遇到了无限500报错。看logs文件夹里的日志,应该是数据库连接成功,但是库名不对。检查了几遍明明是对的,看了一下连接,好像连的是一个不存在的名为PUBLIC的库。又用配置工具配置了几次,依旧不行。
查资料得知配置文件修改的是dbconfig.xml文件。这个文件在/var/atlassian/application-data/jira目录下。赶紧去看了一下。里面有一个莫名其妙的 <schema-name>PUBLIC</schema-name>字段,查遍了官方说明,都没看到有写这个字段。试着把这个字段改成正确的数据库名称,重启Jira,居然可以正常使用了。

4、然后就是进入初始化安装流程,这里选择导入已有数据,然后输入备份数据位置,等待即可。

总结

整个迁移过程说简单也简单,说坑也挺坑的,主要有这么几个点:

1、对Java的SDK对版本和类型(OpenJDK、OracleJDK)有奇怪要求。
2、对Mysql connector版本有奇怪要求,8不行5.1.46可以
3、官方配置工具配置完以后数据库居然不对,需要手动去配置文件里面修改。而这个dbconfig.xml配置文件又找了好久。
4、全都搞完以后日志里有一堆关于mysql连接不是ssl的Warning,害得我又去dbconfig.xml里把连接串url里加了个useSSL=false才正常。

终于可以正常用Jira Software了。这里强烈推荐一下这个管理工具,不管是做团队的项目管理,还是个人的事务管理,都肥肠好用哦。