[zer0pts 2020]wysinwyg
好题
这题加了很多syscall 和 hook
动调的时候转来转去其实不怎么弄得清楚逻辑
由于函数很少 直接逐个查看(其实 这里通过观察 main后面的init函数 可以发现依次调用了 sub_750,sub_932,sub_710 而check就是在sub_932被调用的)
这个一眼就是qpowmod了
然后是关键的check
注意到上面 if(v2=231) 处correct的条件是 dword_202158=0
而看 else if(v2==1) 中dword_202158的赋值 要满足为0 必须 |的全是0
也就是说 powmod(...,...) == dword_202020[] 的值
找到这个数组 结合下面每次 +0.5 可知这个应该就是flag变换后的enc数组
这里其实是个微型的RSA。。。 当然也可以直接将32~128的字符的powmod算出来存个表 挨个查询即可
solution.py
from libnum import *
from primefac import *
enc = [0x1A400138, 0x00000000, 0x279AB867, 0x00000000, 0x177D2969, 0x00000000, 0x0E6E46F5, 0x00000000, 0x512621F8, 0x00000000, 0x2E96CE73, 0x00000000, 0x0484B496, 0x00000000, 0x73414F6E, 0x00000000, 0x0484B496, 0x00000000, 0x01C274E9, 0x00000000, 0x0484B496, 0x00000000, 0x637DC762, 0x00000000, 0x15147A4A, 0x00000000, 0x1FE9895E, 0x00000000, 0x1FE9895E, 0x00000000, 0x862B01EB, 0x00000000, 0x775A06CD, 0x00000000, 0x0E6E46F5, 0x00000000, 0x0E6E46F5, 0x00000000, 0x3E6A2466, 0x00000000, 0x0300AB6D, 0x00000000, 0x5A67CC12, 0x00000000, 0x34167E01, 0x00000000, 0x862B01EB, 0x00000000, 0x0300AB6D, 0x00000000, 0x0484B496, 0x00000000, 0x862B01EB, 0x00000000, 0x0300AB6D, 0x00000000, 0x11EFDA4D, 0x00000000, 0x512621F8, 0x00000000, 0x0E6E46F5, 0x00000000, 0x177D2969, 0x00000000, 0x2E96CE73, 0x00000000, 0x15147A4A, 0x00000000, 0x5A67CC12, 0x00000000, 0x2E96CE73, 0x00000000, 0x7880144D, 0x00000000, 0x5A69ED6B, 0x00000000]
n = 0x8BAE6FA3
e = 0x5BEB
p = 42821
q = 54727
d = modinv(e,(p-1)*(q-1))
flag = b''
for c in enc:
if(c!=0):
flag += n2s(pow(c,d,n))
print(flag)
以上只是粗浅的分析 这题还应该学习ptrace这些的逻辑
ptrace是用来跟踪进程的 结合check方式可以知道
v4 = ptrace(PTRACE_PEEKDATA, a1, a2[13], 0LL);
这句应该是将flag从其他地方跟踪传给v4
在main后面调用的sub_932中
这里应该就有读取flag的操作
学习了一下, PTRACE_PEEKDATA
和 PTRACE_PEEKTEXT
参数是在tracee的内存中读取一个 long 长的数据
关于这里的switch关系 结合源码
可以看到这里是根据 rax 来选择的
而看这个关键函数
刚好switch的v2就是rax的值!
关于ptrace参数格式 data = ptrace(PTRACE_PEEKTEXT, pid, addr, NULL);
这样其实已经能解决ptrace的问题了 具体分析的话还有参数中 a2[13]
即rsi
传递的具体是什么数据 以及为什么下面的a2[12]
就是rdx
(日后再补罢)
还有syscall的hook有空再动调看看
放一份题目的源码在这
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/ptrace.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/wait.h>
int is_wrong;
float cursor;
long flag[] = {440402232, 664451175, 394078569, 242108149, 1361453560, 781635187, 75805846, 1933660014, 75805846, 29521129, 75805846, 1669187426, 353663562, 535398750, 535398750, 2250965483, 2002388685, 242108149, 242108149, 1047143526, 50375533, 1516751890, 873889281, 2250965483, 50375533, 75805846, 2250965483, 50375533, 300931661, 1361453560, 242108149, 394078569, 781635187, 353663562, 1516751890, 781635187, 2021659725, 1516891499};
long powm(long base, long exp, long mod) {
long x;
if (base == 0) return 0;
if (exp == 0) return 1;
if (exp & 1 == 0) {
x = powm(base, exp >> 1, mod);
x = (x * x) % mod;
} else {
x = base % mod;
x = (x * powm(base, exp-1, mod) % mod) % mod;
}
return (long)((x + mod) % mod);
}
void inject(int pid, struct user_regs_struct *regs) {
char c;
switch(regs->orig_rax) {
case SYS_fstat:
is_wrong = 0;
break;
case SYS_brk:
cursor = 0.0;
break;
case SYS_write:
c = ptrace(PTRACE_PEEKDATA, pid, regs->rsi, NULL) & 0xff;
regs->rdx = 1;
is_wrong |= powm(c, 23531, 2343464867) - flag[(int)cursor];
cursor += 0.5;
break;
case SYS_exit_group:
if (is_wrong) {
puts("Wrong!");
} else {
puts("Correct!");
}
break;
}
syscall(SYS_ptrace, PTRACE_SETREGS, pid, NULL, regs);
}
__attribute__ ((constructor)) void __daemon(void) {
struct rusage usage;
struct user_regs_struct regs;
int pid, s;
pid = syscall(SYS_fork);
if (pid == 0) {
syscall(SYS_ptrace, PTRACE_TRACEME, 0, 0, 0);
syscall(SYS_kill, syscall(SYS_getpid), SIGSTOP);
} else {
syscall(SYS_wait4, pid, &s, 0, &usage);
syscall(SYS_ptrace, PTRACE_SETOPTIONS, pid, NULL, PTRACE_O_TRACESYSGOOD);
while(1) {
syscall(SYS_ptrace, PTRACE_SYSCALL, pid, NULL, NULL);
syscall(SYS_wait4, pid, &s, 0, &usage);
if (WIFSTOPPED(s) && (WSTOPSIG(s) & 0x80)) {
syscall(SYS_ptrace, PTRACE_GETREGS, pid, NULL, ®s);
inject(pid, ®s);
}
if (WIFEXITED(s)) syscall(SYS_exit_group, 0);
}
}
}
int main(int argc, char **argv) {
if (argc == 2) {
puts(argv[1]);
} else {
puts("Feed me flag");
}
return 0;
}