Hi there! 👋

Good morning, and in case I don’t see ya, good afternoon, good evening, and good night.

定点数和浮点数

定点和浮点中的“点”指的是小数点,定点数在比特位的定义上确定了小数点的位置,而浮点数使用更复杂的表示方式,导致小数点在若干个比特位上没有直接体现,所以称它是浮点。 定点数 1. “定点"表示的整数 4-bit无符号整数可以用下面这种方式来表示: 整数不存在小数点,也可以说我们默认小数点固定在整数的末尾,所以整数的表示也可以看作是“定点”。 2. 定点表示的小数 使用7位二进制,前4位表示整数部分,后3位表示小数部分,可以这样表示: $$ \begin{array}{c:c:c:c|c:c:c} 2^3 & 2^2 & 2^1 & 2^0 & 2^{-1} & 2^{-2} & 2^{-3} \end{array} $$ 小数点固定在第4、第5个比特之间,分别计算每个位置的值并求和即可得到这段二进制表示的小数值: 可以表示的范围是 $[0.0, 15.875]$,表示的数之间的最小间隔是 $0.125$,并且间隔是均匀的。 定点数的特点: 定点数和整数的表示很接近,计算也像整数一样简单高效; 几乎可以重用为整数运算设计的硬件; 表示的数值间隔均匀,但是整体范围较小。 浮点数 为了方便理解,我们还是从最简单的无符号整数开始,逐步定义出浮点数。 4-bit可以表示出集合 $A=\{i|0\leq i \leq 15, i\in \Z\}$,如果把它们看作 $2$ 的指数,就可以表示出数值更大的集合 $B=\{2^i|i\in A\}$,但是数据变得非常稀疏,并且是距离0越远越稀疏。 前 $4$ 位二进制可以称为指数(Exponent),简写为 $E$;为了表示小数,我们再加入 $3$ 位尾数(Mantissa),简写为 $M$,尾数部分和之前的计算方式相同: $$ \begin{array}{c:c:c} 2^{-1} & 2^{-2} & 2^{-3} \end{array} $$ 例如:尾数101可以计算得到 $\bold{1}\times 0.5+\bold{0}\times 0.25+\bold{1}\times 0.125=0.625$ 将指数部分的值与尾数部分的值相乘得到十进制的结果:...

September 17, 2024 · 2 min · Slightwind

Quantization Impact on Model Accuracy

Mistral-7B’s performance on 5-shot MMLU 如果对测试细节不感兴趣,只需要看下面给出的汇总表格即可。 Overview 量化/非量化版本的 Mistral-7B-v0.1 模型在 5-shot MMLU 上的表现: Quant Type Compute Dtype Double Quant Group Size Avg (%) Total Time (s) BF16 BF16 N/A N/A $61.00$ $312.79$ INT8 BF16&INT8 N/A N/A $60.87$ $614.43$ FP4 FP16 False 64 $59.37$ $347.00$ FP4 FP16 True 64 $59.17$ $353.22$ FP4 FP32 False 64 $59.50$ $1061.27$ NF4 FP16 False 64 $59.04$ $361.19$ NF4 FP16 False 128 $58.78$ $352.65$ AWQ-q4 FP16 N/A 128 $59....

March 1, 2024 · 3 min · Slightwind

Install OpenSSL and GmSSL on Win32

由于参与了一个在 PLC 和上位机之间建立加密信道的项目,需要在PLC的Win7-32bit系统中安装OpenSSL和GmSSL,因为PLC硬盘太小,所以我实际上是在虚拟机里面进行的编译。 OpenSSL 一开始是打算编译一下的,下载了OpenSSL的源码,OpenSSL的Configure是依赖Perl的。然后下载安装了Strawberry Perl for win32,然后发现会出现各种报错,一番搜索了解到需要安装ActivePerl: Install ActivePerl and remove Stawberry Perl as it is not compatible with openssl. 但是ActivePerl的官网只提供64bit的版本,安装32bit版本的ActivePerl需要支付$912/yr: The site states: “if you need 32-bit or other older/legacy versions, they are available through our new ActiveState Platform by subscribing to at least Team Tier. See pricing here.” 这就很难搞,只能去下载安装现成的二进制文件:http://slproweb.com/products/Win32OpenSSL.html GmSSL GmSSL官方的编译与安装教程虽然字数不多但是很有帮助,编译过程比较顺利。 虽然也提及要用ActivePerl,但是我在对Configure进行了一点简单修改之后,用Strawberry Perl也可以成功运行perl Configure VC-WIN32。 直接运行perl Configure VC-WIN32会遇到报错:"glob" is not exported by the File::Glob module。 分别在Configure和test/build.info两个文件中,把: use if $^O ne "VMS", 'File::Glob' => qw/glob/; 修改为:...

December 8, 2021 · 1 min · Slightwind

使用树莓派4B作为一台服务器

树莓派是个一直听说,但是一直没玩过的东西,所以在今年年初搞了一块折腾了一段时间。在上面起了一些服务,确实很好玩。在上面搭建了私有网盘、Minecraft、SageMath 还有几个密码学题目。这篇博客记录了我折腾树莓派的经历~ 解决公网IP问题 我想在公网连接到家里的树莓派,访问到上面的服务,所以需要有公网IP或者使用 frp 内网穿透。当然如果不需要让树莓派暴露在公网下,就不需要搞公网 IP 了。 静态公网IP 如果有角度可以搞到企业专线,那还是很香的,不仅拥有运营商分配的静态公网 IP,还有上下行相等的大带宽,当然费用也很高,也需要注册的企业资质。所以我是搞不到静态的公网 IP。 动态公网IP 没有静态的,可以退而求其次搞动态的,跟运营商交涉一下是可以得到动态的公网 IP 的,虽然是上下行不对等的家庭带宽,但是作为服务器来说绰绰有余,已经远超很多便宜的云服务器了。 第一次我直接跟人工客服打电话申请要一个静态公网IP被拒绝了;然后第二天我又一次联系了人工客服,询问能不能申请动态的公网IP(可以说装摄像头要用到,不能说在家里搭建服务器),结果很快就回电通知我已经给了动态的公网IP,还算顺利~ Dynamic DNS 后面使用发现,我们这边的动态的公网IP大约2~3天变动一次,这就可以通过 Dynamic DNS(DDNS) 将动态的IP解析到固定的域名,就能通过固定的域名访问到服务器了。 DDNS需要服务端和本地各运行一个服务:本地的树莓派或路由器上运行一个服务,每隔一段时间(几分钟)就获取一下自己的公网IP,判断一下有没有发生改变,如果发生改变就将新的 IP 发送给服务端,服务端得到新的 IP,就重新将域名解析到新的IP,所以是动态DNS。 DDNS的服务端只提供域名的动态解析服务,所以服务端的带宽对访问树莓派的速度没有影响(但是可能会影响到延时?实际使用没有明显感觉到) DDNS服务: 直接使用一些网站(oray.com/3322.org/Dyndns.com/No-ip.com)免费提供的DDNS服务,但是他们给的域名都是比较杂乱的三级域名,需要再把自己租的阿里云/腾讯云域名CNAME解析到这个三级域名。花生壳(oray.com)可以免费使用;而No-ip.com免费版需要每30天登录上去手动续约。 使用自己的vps运行脚本为树莓派提供DDNS服务,由于需要通过脚本进行域名解析,所以需要在vps上安装对应的SDK,然后开发对应的脚本,可以直接将自己的阿里云/腾讯云域名解析到家里的公网IP。 我现在是选择使用花生壳(oray.com)的DDNS服务,只需要注册即可得到一个三级域名,通过控制台->域名->壳域名来查看。我的路由器是小米 4A,可以在后台设置DDNS,选择“花生壳”并输入账号密码域名和检查 IP 的时间间隔即可。路由器不支持的话就需要在树莓派上运行一个脚本来发送新的IP。 也有很多树莓派玩家通过每次变动IP时,让树莓派将新IP发送给自己的邮箱,使自己总是可以知道最新的IP地址。 frp内网穿透 如果也申请不到动态 IP,那就只能用 frp 做内网穿透了,需要借助一台有公网 IP 的 vps,流量也都需要经过这台 vps,所以享受不到家庭宽带的低价大带宽了。 测试上下行带宽 可以在 speedtest.cn 测试下行带宽和上行带宽(最好直接连网线测)。 从公网访问树莓派下载文件需要的是家里的上行带宽,而家庭宽带的上行都是很低的,只能去升级下行带宽,上行才能对应的提升一点。。。。所以如果感觉带宽不太够还是要去升级一下宽带的。 我家的联通宽带就不太行,一开始是100M下行,20M上行,实测大约下行90~100M,上行20~40M。于是换了500M下行,50M上行的宽带,实测大约下行450~550M,上行60~70M。 组装树莓派和安装Ubuntu 我的是树莓派 4B。启动树莓派还需要有 5V 3A 的电源和一张 TF 卡。 各版本树莓派的对照表:https://shumeipai.nxez.com/wp-content/uploads/2017/03/raspberrypi-version-compare-4b.png 然后就是愉快的组装环节,树莓派 PCB 边缘是有毛糙的,最好用砂纸磨光滑再装到壳子里。 写入Ubuntu镜像 树莓派支持安装很多种系统,我选择的是 Ubuntu Server 20.04.2 LTS 64-bit,可以在这里下载:https://ubuntu.com/download/raspberry-pi,先把镜像下载到本地,把 TF 卡插到读卡器里,再把读卡器插在这台电脑上。...

November 17, 2021 · 4 min · Slightwind

湖湘杯 2021 Crypto

hxb 2021 crypto signin $n1/n2$ 的连分数展开是对 $q1/q2$ 的一个逼近,所以枚举连分数中的每一项,就可以得到 $q1, q2$ 了,分解之后正常进行 RSA 解密得到 flag。 from Crypto.Util.number import GCD, inverse, long_to_bytes, isPrime pk = (1150398070565459492080597718626032792435556703413923483458704675295997646493249759818468321328556510074044954676615760446708253531839417036997811506222349194302791943489195718713797322878586379546657275419261647635859989280700191441312691274285176619391539387875252135478424580680264554294179123254566796890998243909286508189826458854346825493157697201495100628216832191035903848391447704849808577310612723700318670466035077202673373956324725108350230357879374234418393233, 1242678737076048096780023147702514112272319497423818488193557934695583793070332178723043194823444815153743889740338870676093799728875725651036060313223096288606947708155579060628807516053981975820338028456770109640111153719903207363617099371353910243497871090334898522942934052035102902892149792570965804205461900841595290667647854346905445201396273291648968142608158533514391348407631818144116768794595226974831093526512117505486679153727123796834305088741279455621586989) c1, c2 = (361624030197288323178211941746074961985876772079713896964822566468795093475887773853629454653096485450671233584616088768705417987527877166166213574572987732852155320225332020636386698169212072312758052524652761304795529199864805108000796457423822443871436659548626629448170698048984709740274043050729249408577243328282313593461300703078854044587993248807613713896590402657788194264718603549894361488507629356532718775278399264279359256975688280723740017979438505001819438, 33322989148902718763644384246610630825314206644879155585369541624158380990667828419255828083639294898100922608833810585530801931417726134558845725168047585271855248605561256531342703212030641555260907310067120102069499927711242804407691706542428236208695153618955781372741765233319988193384708525251620506966304554054884590718068210659709406626033891748214407992041364462525367373648910810036622684929049996166651416565651803952838857960054689875755131784246099270581394) n1, n2 = pk e = 0x10001 def getRoot(x, n): high = 1 while high ** n <= x: high *= 2 low = high // 2 while low < high: mid = (low + high) // 2 if low < mid and mid**n < x: low = mid elif high > mid and mid**n > x: high = mid else: return mid return mid + 1 # https://github....

November 16, 2021 · 7 min · Slightwind

ByteCTF 2021 Crypto

easyxor shift函数是个常见的移位异或操作,convert是对一个数字使用不同的 key 和 mask 进行 4 次移位异或,这个函数在已知 key 的情况下是可逆的。 encrypt函数是对明文块进行两种模式(CBC和OFB)的块加密,块长度为 8,对于每一块的加密使用的就是上面的convert函数。 首先通过密文的长度可以得知一共被分成了 6 块;前 3 块明文使用 OFB 模式,后三块明文使用 CBC 模式;keys 是一个长度为 4 的列表,列表中每个值的范围是(-32, 32),$64^4$ 爆破也是可以接受的。 读完题目代码之后可以想到其实我们已经知道第一块明文了,就是 flag 的格式ByteCTF{,而OFB模式实际上是加密的key,最终结果和明文块异或,所以第一个明文块异或第一个密文块就可以知道第一个 key 加密的结果,也就是cur_c = convert(last, k)的cur_c,这样就可以得到第二块的 last。 现在对于第二块,已知 IV(last),未知 keys,已知明文是可显示字符,所以可以爆破 keys 了,把能解出可显示字符明文的 keys 都保留出来,发现有 4836 个 keys 是满足的,那么我们还要借助第三块再筛一次,最终只得到一组 keys。 from itertools import product from tqdm import tqdm from Crypto.Util.number import bytes_to_long, long_to_bytes def check(s): return min([((i < 129) and (i > 31)) for i in s]) c = "89b8aca257ee2748f030e7f6599cbe0cbb5db25db6d3990d3b752eda9689e30fa2b03ee748e0da3c989da2bba657b912" c_list = [int(c[i*16:i*16+16], 16) for i in range(len(c) // 16)] known_m = bytes_to_long(b'ByteCTF{') range64 = list(range(-32, 33)) cur_c = known_m ^ c_list[0] print(cur_c) k_cnt = 0 for a,b,c,d in tqdm(product(range64, range64, range64, range64)): last = cur_c k = [a, b, c, d] try_cur_c = convert(last, k) m1 = long_to_bytes(try_cur_c ^ c_list[1]) if check(m1): # 只筛选这第一轮的话,4836个k是满足条件的,所以得筛第二轮 last = try_cur_c try_cur_c = convert(last, k) m2 = long_to_bytes(try_cur_c ^ c_list[2]) if check(m2): k_cnt += 1 try: print(m1....

October 29, 2021 · 8 min · Slightwind

Install OpenWrt for Redmi Router AC2100

Get shell 小米路由器后台管理页面是不给我们上传并且刷入新固件的,所以要先拿到 shell,ssh 连上路由器就可以往里面刷入新固件了。 先正常启动路由器,并进入路由器后台管理页面,这时可以在浏览器的地址栏看到自己路由器的内网 IP,和自己的 stok,例如我的开头是: http://10.161.145.162/cgi-bin/luci/;stok=e9974e290dd74c4683328c5a5876308b/... 我的路由器 IP 是10.161.145.162,stok的值为e9974e290dd74c4683328c5a5876308b,现在把下面的链接替换成自己的,然后 Enter,浏览器返回0说明这一步可以了。 http://「这里替换IP」/cgi-bin/luci/;stok=「stok的值」/api/misystem/set_config_iotdev?bssid=Xiaomi&user_id=longdike&ssid=-h%3B%20nvram%20set%20ssh_en%3D1%3B%20nvram%20commit%3B%20sed%20-i%20's%2Fchannel%3D.*%2Fchannel%3D%5C%22debug%5C%22%2Fg'%20%2Fetc%2Finit.d%2Fdropbear%3B%20%2Fetc%2Finit.d%2Fdropbear%20start%3B 然后下面这个链接也是一样的操作,同样应该返回0: http://「这里替换IP」/cgi-bin/luci/;stok=「stok的值」/api/misystem/set_config_iotdev?bssid=Xiaomi&user_id=longdike&ssid=-h%3B%20echo%20-e%20'12345678%5Cn12345678'%20%7C%20passwd%20root%3B 如果这两个链接都成功返回了0,那么就可以使用习惯的工具去 ssh 连接路由器了: ssh root@「这里替换IP」 # passwd 12345678 不出意外,这边是可以连接到路由器的 shell 的,然后可以看到字符画显示的are you ok。 上传并刷入固件 前面拿到了 shell,现在可以上传固件了,首先下载openwrt-RM2100-kernel1.bin和openwrt-RM2100-rootfs0.bin,然后 cd 进入这两个文件所在的目录,用 SCP 传到路由器上。 # 把openwrt的固件通过SCP上传到路由器的/tmp目录下 scp openwrt-RM2100-kernel1.bin root@「这里替换IP」:/tmp scp openwrt-RM2100-rootfs0.bin root@「这里替换IP」:/tmp 然后 ssh 连接上路由器,开始刷入固件: # 进入/tmp目录下 cd /tmp mtd write openwrt-RM2100-kernel1.bin kernel1 nvram set uart_en=1 nvram set bootdelay=5 nvram set flag_try_sys1_failed=1 nvram commit mtd -r write openwrt-RM2100-rootfs0.bin rootfs0 等待写入完成,就可以重启路由器了,这个时候路由器的 Wi-Fi 名称变成了 OpenWrt,并且没有密码,可以直接连接,然后用 ssh 连接新的 IP:...

October 10, 2021 · 1 min · Slightwind

Install SageMath for Apple Silicon M1

Install conda 官网上没有直接给出 M1 Mac 版本的 SageMath 二进制安装文件,不过给出了使用 conda 安装 Sage 的方法,参考Install from conda-forge。 所以如果自己的 Mac 上还没有安装 conda 的话,可以先安装一下,然后使用 conda 安装 SageMath。 首先下载Miniforge3-MacOSX-arm64.sh,cd 进入Miniforge3-MacOSX-arm64.sh所在的目录。 bash Miniforge3-MacOSX-arm64.sh 接着一路回车,直到确认条款: Do you accept the license terms? [yes|no] [no] >>> yes 然后编辑配置文件vim ~/.zshrc,在最下面加入如下内容: path=('/Users/「这里替换成Mac用户名」/miniforge3/bin' $path) export PATH :wq保存并退出,然后source ~/.zshrc,conda info应该就可以看到了,到这里 conda 安装完成。 在终端输入下面这些,给 conda 换到清华源,这样在使用国内网络不走代理的情况下安装一些东西就更快了: conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/main/ conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/free/ conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/conda-forge/ conda config --add channels https://mirrors....

October 9, 2021 · 1 min · Slightwind

Official Solution to the "lowExponent" Problem in NepCTF2021

这题使用的加密算法是 Demytko,属于一种类似 RSA 的在椭圆曲线上的加密算法,这题的攻击思路也是可以完全类比 RSA Hastad 广播攻击。 加密后的结果是椭圆曲线上的点, Division Polynomials 使我们可以用仅含一个未知数的多项式来表示这个点的 $x$ 坐标: $$ \begin{aligned} \psi_{-1} &=-1 \\ \psi_{0} &=0 \\ \psi_{1} &=1 \\ \psi_{2} &=2 y \\ \psi_{3} &=3 x^{4}+6 a x^{2}+12 b x-a^{2} \\ \psi_{4} &=4 y\left(x^{6}+5 a x^{4}+20 b x^{3}-5 a^{2} x^{2}-4 a b x-8 b^{2}-a^{3}\right) \\ \psi_{2 i+1} &=\psi_{i}\left(\psi_{i+2} \psi_{i-1}^{2}-\psi_{i-2} \psi_{i+1}^{2}\right) / 2 y, i \geq 2 \\ \psi_{2 i} &=\psi_{i+2} \psi_{i}^{3}-\psi_{i+1}^{3} \psi_{i-1}, i \geq 3 \end{aligned} $$...

July 20, 2021 · 2 min · Slightwind

0xGame 2020 Crypto Problems

0xGame2020是第一届0xGame比赛,时间持续一个月,面向零基础的新生。题目和exp可以在我的GitHub上找到:https://github.com/Am473ur/My-CTF-Challenge/tree/main/0xGame2020 ,这里记录一下出题人角度的 wp。 Week 1 Calendar 题目给了一张图片和一串逗号隔开的坐标信息,没看出来的话不难想到去百度一下“日历加密”,这题只是做了简单的修改。 SAT1,THU1,MON3,MON2,WED3,SUN2,THU1,SUN4,FRI3,THU1,MON4,MON4,FRI4,THU3,SUN4,SUN2,TUE4,THU1,FRI1,MON3,MON2 懒得百度的话,也不难看出前三个字母代表周一到周日,紧跟的数字范围是 1~4,所以他们代表两个坐标,列举出来并用a~z替换1~26,即可得到 flag。 easyXor 做出这题只需要知道异或的逆运算还是异或,反过来跑一遍就拿到了flag。 exp: cipher = [72, 63, 38, 12, 8, 30, 30, 6, 82, 4, 84, 88, 92, 7, 79, 29, 8, 90, 85, 26, 25, 87, 80, 10, 20, 20, 9, 4, 80, 73, 31, 5, 82, 0, 1, 92, 0, 0, 94, 81, 4, 85, 27, 35] flag = "" cipher += [ord("^")] for i in range(len(cipher)-1): flag = chr(cipher[len(cipher) - i - 2] ^ cipher[len(cipher) - i - 1]) + flag cipher[len(cipher) - i - 2] = ord(flag[0]) print(flag) # 0xGame{ec15a9eb-08b7-4c39-904d-27eed888f73f} 发现有的学弟跑完脚本手动补0,exp正确的话,是可以得到完整flag的。...

December 21, 2020 · 8 min · Slightwind