H@cktivityCon 2021 CTF - Words Church
aszx87410 opened this issue · 0 comments
aszx87410 commented
Description
Tired of finding bugs and exploiting vulnerabilities? Want a classic brain buster instead? Why not play a wordsearch -- in fact, why not play thirty word searches!!
Writeup
Nothing special, just parse strings and find the answer. The only problem is I am not familiar with the rules, I found that the coordinate can be a negative number. I thought it's a bug but it turns out it's valid.
var NetcatClient = require('node-netcat').client;
var client = NetcatClient(32332, 'challenge.ctf.games');
client.on('open', function () {
console.log('connect');
});
let stage = 'before_start'
let board = []
let problem = null
let buffer = []
let timer = null
// x, y
let dir = [
[-1, 1],
[0, 1],
[1, 1],
[-1, -1],
[-1, 0],
[0, -1],
[1, -1],
[1, 0],
]
function isAns(board, x, y, problem) {
if (board[y][x] !== problem[0]) return null
if (problem.length === 1) {
return `[(${x},${y})]`
}
let steps = []
let isFound = false
for(let d of dir) {
let nowX = x
let nowY = y
let stepX = x
let stepY = y
let count = 1
steps.push([x,y])
while(true) {
nowX += d[0];stepX += d[0]
nowY += d[1];stepY += d[1]
if (nowX === -1) { nowX = 15 }
if (nowX === 16) { nowX = 0 }
if (nowY === -1) { nowY = 15 }
if (nowY === 16) { nowY = 0 }
if (board[nowY] && board[nowY][nowX] === problem[count]) {
count++
steps.push([stepX,stepY])
if (count === problem.length) {
isFound = true
break
}
} else {
break
}
}
if (isFound) {
break
} else {
steps = []
}
}
if (!isFound) {
return null
}
console.log('found ans!')
const aaa = '[' + steps.map(arr => `(${arr[0]}, ${arr[1]})`).join(', ') + ']'
console.log(aaa)
return aaa
}
function findAns() {
for(let y=0; y<board.length; y++) {
for(let x=0; x<board[y].length; x++) {
if (board[y][x] !== problem[0]){
continue
}
//console.log('log:', x, y)
let result = isAns(board, x, y, problem)
if (result) {
return result
}
}
}
}
function parseBoard() {
board = board.filter(row => row !== '')
const lastIndex = board.findIndex(row => row.includes('---') && row.length < 10)
board = board.slice(2, lastIndex)
board = board.map(row => {
let r = row.replace(/\s/g, '').split('|')[1]
return r
})
}
function handler() {
if (stage === 'before_start' && buffer.includes('> ')) {
stage = 'receiving_board'
client.send('play\n')
buffer = []
return
}
if (stage === 'receiving_board') {
stage = 'receiving_problem'
board = []
let index = buffer.findIndex(line => line.includes(': X'))
for(let i=index; i<buffer.length; i++) {
board.push(buffer[i])
}
parseBoard()
console.log('[log] board:')
console.log(board)
let p = buffer[buffer.length - 1]
problem = p.replace(/[:> \n\t]/g, '')
console.log('[log] problem:', problem, problem.length)
client.send(findAns() + "\n")
buffer = []
return
}
if (stage === 'receiving_problem') {
if (buffer.find(l => l.includes('Onto the'))) {
console.log('[log] next level')
stage = 'receiving_board'
handler()
return
}
problem = buffer.join('').replace(/[:> \n\t]/g, '')
console.log('[log] problem:', problem, problem.length)
client.send(findAns() + "\n")
buffer = []
return
}
}
client.on('data', function (data) {
let str = data.toString('ascii')
let lines = str.split('\n')
console.log(str)
buffer.push(...lines)
clearTimeout(timer)
timer = null
timer = setTimeout(handler, 1000)
});
client.on('error', function (err) {
console.log(err);
});
client.on('close', function () {
console.log('close');
});
client.start();