started palindromatic task of bi0sCTF 23
This commit is contained in:
241
bi0sctf23/pwn/palindromatic/src/palindromatic.c
Normal file
241
bi0sctf23/pwn/palindromatic/src/palindromatic.c
Normal file
@@ -0,0 +1,241 @@
|
||||
#include "linux/random.h"
|
||||
#include "palindromatic_util.c"
|
||||
|
||||
char *temp_buffer;
|
||||
unsigned long magic;
|
||||
queue_t incoming_queue;
|
||||
queue_t outgoing_queue;
|
||||
bool sanitized = false;
|
||||
|
||||
/*
|
||||
Copy request from user and add to start of queue
|
||||
*/
|
||||
static noinline long pm_add_request(arg_t *arg)
|
||||
{
|
||||
long idx = -1;
|
||||
request_t *req = kmem_cache_zalloc(pm_cache, GFP_KERNEL);
|
||||
if(!req) goto end;
|
||||
|
||||
req->type = RAW;
|
||||
req->magic = magic;
|
||||
if(copy_from_user(req->str, arg->buffer, STRING_SZ))
|
||||
{
|
||||
kfree(req);
|
||||
goto end;
|
||||
}
|
||||
idx = pm_queue_enqueue(&incoming_queue, req);
|
||||
|
||||
end:
|
||||
return idx;
|
||||
}
|
||||
|
||||
/*
|
||||
Accept characters only in [A-Z|a-z] and translate to [A-Z]
|
||||
Only 1 sanitize is allowed
|
||||
*/
|
||||
static noinline long pm_sanitize_request(void)
|
||||
{
|
||||
long idx = -1;
|
||||
|
||||
request_t *req = pm_queue_peek(&incoming_queue);
|
||||
if(!req) goto end;
|
||||
if(req->type == SANITIZED) goto end;
|
||||
|
||||
memset(temp_buffer, 0x0, STRING_SZ);
|
||||
|
||||
int ptr = 0;
|
||||
for(int i = 0; i < STRING_SZ; i++)
|
||||
{
|
||||
if(!req->str[i]) break;
|
||||
|
||||
if(req->str[i] > 0x60 && req->str[i] < 0x7b)
|
||||
temp_buffer[ptr++] = req->str[i]-0x20;
|
||||
|
||||
else if(req->str[i] > 0x40 && req->str[i] < 0x5b)
|
||||
temp_buffer[ptr++] = req->str[i];
|
||||
|
||||
else continue;
|
||||
}
|
||||
|
||||
temp_buffer[ptr] = 0;
|
||||
strcpy(req->sanstr, temp_buffer);
|
||||
req->type = SANITIZED;
|
||||
|
||||
idx = pm_queue_enqueue(&incoming_queue, pm_queue_dequeue(&incoming_queue));
|
||||
|
||||
end:
|
||||
return idx;
|
||||
}
|
||||
|
||||
/*
|
||||
If request is raw, remove it
|
||||
else, set it to raw and send it back to start of the queue
|
||||
*/
|
||||
static noinline long pm_reset_request(void)
|
||||
{
|
||||
request_t *req = pm_queue_dequeue(&incoming_queue);
|
||||
if(!req) return -1;
|
||||
|
||||
if(req->type != RAW)
|
||||
{
|
||||
req->type = RAW;
|
||||
memset(req->sanstr, 0x0, sizeof(req->sanstr));
|
||||
pm_queue_enqueue(&incoming_queue, req);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
kfree(req);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
Check if it is a palindrome or not and set type accordingly
|
||||
Remove from incoming queue and add to outgoing queue
|
||||
*/
|
||||
static noinline long pm_process_request(void)
|
||||
{
|
||||
long idx = -1;
|
||||
|
||||
request_t *req = pm_queue_peek(&incoming_queue);
|
||||
if(!req) goto end;
|
||||
if(req->magic != magic) goto end;
|
||||
int len = req->type==SANITIZED?strlen(req->sanstr):strlen(req->str);
|
||||
if(!len) goto end;
|
||||
idx = pm_queue_enqueue(&outgoing_queue, req);
|
||||
if(idx < 0) goto end;
|
||||
|
||||
memset(temp_buffer, 0x0, STRING_SZ);
|
||||
if(req->type == RAW)
|
||||
{
|
||||
for(int i = (len/2)-1; i > -1; i--)
|
||||
{
|
||||
if(req->str[i] < 0x41 || req->str[i] > 0x5a) break;
|
||||
temp_buffer[i] = req->str[i];
|
||||
}
|
||||
temp_buffer[len/2] = 0;
|
||||
|
||||
if(strcmp(temp_buffer, &req->str[len/2]+len%2)) req->type = NONPALINDROME;
|
||||
else req->type = PALINDROME;
|
||||
pm_queue_dequeue(&incoming_queue);
|
||||
}
|
||||
|
||||
if(req->type == SANITIZED)
|
||||
{
|
||||
for(int i = (len/2)-1; i > -1; i--) temp_buffer[i] = req->sanstr[i];
|
||||
temp_buffer[len/2] = 0;
|
||||
|
||||
if(strcmp(temp_buffer, &req->sanstr[len/2]+len%2)) req->type = NONPALINDROME;
|
||||
else req->type = PALINDROME;
|
||||
pm_queue_dequeue(&incoming_queue);
|
||||
}
|
||||
|
||||
end:
|
||||
return idx;
|
||||
}
|
||||
|
||||
/*
|
||||
Get result of first request in outgoing queue
|
||||
*/
|
||||
static noinline long pm_reap_request(void)
|
||||
{
|
||||
request_t *req = pm_queue_dequeue(&outgoing_queue);
|
||||
if(!req) return -1;
|
||||
if(req->magic != magic) return -1;
|
||||
|
||||
long ret = req->type==PALINDROME?1:0;
|
||||
kfree(req);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
Get the available slots in both queues
|
||||
*/
|
||||
static noinline long pm_query_capacity(void)
|
||||
{
|
||||
long ret = (QUEUE_SZ-pm_queue_count(&outgoing_queue))<<16
|
||||
| (QUEUE_SZ-pm_queue_count(&incoming_queue));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static long pm_ioctl(struct file *file, unsigned int cmd, unsigned long uarg)
|
||||
{
|
||||
arg_t arg;
|
||||
long ret = -1;
|
||||
mutex_lock(&lock);
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case QUEUE:
|
||||
if(copy_from_user(&arg, (void *)uarg, sizeof(arg_t))) goto end;
|
||||
ret = pm_add_request(&arg);
|
||||
break;
|
||||
|
||||
case SANITIZE:
|
||||
if(sanitized) goto end;
|
||||
sanitized = true;
|
||||
ret = pm_sanitize_request();
|
||||
break;
|
||||
|
||||
case RESET:
|
||||
ret = pm_reset_request();
|
||||
break;
|
||||
|
||||
case PROCESS:
|
||||
ret = pm_process_request();
|
||||
break;
|
||||
|
||||
case REAP:
|
||||
ret = pm_reap_request();
|
||||
break;
|
||||
|
||||
case QUERY:
|
||||
ret = pm_query_capacity();
|
||||
break;
|
||||
|
||||
default:
|
||||
goto end;
|
||||
}
|
||||
|
||||
end:
|
||||
mutex_unlock(&lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int __init init_palindromatic(void)
|
||||
{
|
||||
if(misc_register(&pm_device) < 0) goto err;
|
||||
|
||||
pm_cache = kmem_cache_create("palindromatic", TARGET_SZ, __alignof__(request_t),
|
||||
SLAB_ACCOUNT | SLAB_PANIC | SLAB_HWCACHE_ALIGN | SLAB_NO_MERGE, NULL);
|
||||
if(!pm_cache) goto err;
|
||||
|
||||
temp_buffer = kzalloc(TARGET_SZ, GFP_KERNEL);
|
||||
if(!temp_buffer) goto err;
|
||||
|
||||
get_random_bytes(&magic, sizeof(magic));
|
||||
pm_queue_init(&incoming_queue);
|
||||
pm_queue_init(&outgoing_queue);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if(pm_cache) kmem_cache_destroy(pm_cache);
|
||||
printk(KERN_ALERT "[-] Failed to register pipeparty");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void __exit exit_palindromatic(void)
|
||||
{
|
||||
kfree(temp_buffer);
|
||||
kmem_cache_destroy(pm_cache);
|
||||
misc_deregister(&pm_device);
|
||||
}
|
||||
|
||||
module_init(init_palindromatic);
|
||||
module_exit(exit_palindromatic);
|
||||
Reference in New Issue
Block a user