[zer0pts 2020]wysinwyg

好题
这题加了很多syscall 和 hook
动调的时候转来转去其实不怎么弄得清楚逻辑
由于函数很少 直接逐个查看(其实 这里通过观察 main后面的init函数 可以发现依次调用了 sub_750,sub_932,sub_710 而check就是在sub_932被调用的)
image
这个一眼就是qpowmod了
然后是关键的check
image

注意到上面 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中
image
这里应该就有读取flag的操作
学习了一下, PTRACE_PEEKDATAPTRACE_PEEKTEXT 参数是在tracee的内存中读取一个 long 长的数据
关于这里的switch关系 结合源码
image
可以看到这里是根据 rax 来选择的
而看这个关键函数
image
刚好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, &regs);
        inject(pid, &regs);
      }
      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;
}
posted @ 2023-11-01 09:39  N0zoM1z0  阅读(12)  评论(0编辑  收藏  举报