From 16580534440f2cb0d6b71b946dd164ee70729937 Mon Sep 17 00:00:00 2001 From: retoor Date: Fri, 29 Nov 2024 00:16:16 +0100 Subject: [PATCH] Initial commit. Start of project! --- .clang-format | 192 ++++++++++++++++++++++++++++++++++++++++++++++ .gitignore | 3 + Makefile | 13 ++++ README.md | 23 ++++++ io.h | 84 ++++++++++++++++++++ l33t.c | 50 ++++++++++++ missions/all.h | 3 + missions/runner.h | 17 ++++ missions/vim1.h | 11 +++ proc.h | 48 ++++++++++++ state.h | 23 ++++++ str.h | 17 ++++ subprocess.h | 48 ++++++++++++ 13 files changed, 532 insertions(+) create mode 100644 .clang-format create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 io.h create mode 100644 l33t.c create mode 100644 missions/all.h create mode 100644 missions/runner.h create mode 100644 missions/vim1.h create mode 100644 proc.h create mode 100644 state.h create mode 100644 str.h create mode 100644 subprocess.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..de7da58 --- /dev/null +++ b/.clang-format @@ -0,0 +1,192 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Right +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: MultiLine +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 140 +CommentPragmas: '^ IWYU pragma:' +QualifierAlignment: Leave +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: BinPack +BasedOnStyle: '' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: true +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 1 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: false +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Right +PPIndentWidth: -1 +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Latest +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a6e6abd --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +a.out +.history +l33t \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aa43e75 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +CC = gcc +# For now disabled +# CFLAGS = -Wall -Werror -Wextra -pedantic -Ofast -std=c2x + +all: build run + +build: l33t + +l33t: io.h proc.h state.h str.h subprocess.h l33t.c + $(CC) $(CFLAGS) l33t.c -o l33t + +run: + ./l33t diff --git a/README.md b/README.md new file mode 100644 index 0000000..f045766 --- /dev/null +++ b/README.md @@ -0,0 +1,23 @@ +# l33t certification application + +## About +This application is the only way to certify yourself as a 1337 hacker / system administrator / programmer. It contains challenging tasks like running an HTTP server on a non custom port. Any way is allowed, users have root access and are allowed to install Python or Node or whatever way they would start an HTTP server. Next one is to scan popular ports for example. It sounds complex to make but I've found the ultimate way to do it and already finished the basics. Waiting until a user opened a process for example. Another task could be, run three times ping concurrently. Ping using ipv6, ping using ipv4. Wipe your hard drive using rm (check if they think about --preserve root paramater when doing the rf). The core funcionality of the app is mainly checking ports of started services, listening to ports if they get penetrated, checking if apps are executed or used if required. The process part is already programmed in a decent way! No hacking in this hacking app! + +## What will the end product will be? +The end product will be a (full screen?) page with a full blown terminal (xtermjs). This one connect's straight to a docker container specially initiated for the user. Here the users have root access and can do whatever they want to finish the tests. The idea is that own ways to resolve the tasks is possible, because there are many ways to rome. + +## How does it work +The source code you see in this repository is a command line application. We configure the connection to run this app inside the container. When exited - it will break the connection. This application is a multiplexer allowing us to monitor all user's steps like if an app is opened / how far he is with the task / if he is cheating on the task. After working on cloud management services like this for three years I do not expect to run in a lot of technical issues. Most things I've already done professionally. + +## Contributing +If you like to contribute, contact me @ retoor@molodetz.nl or dR. +Contributing can be in the following forms: + - Creating tests (requires C skills, but maybe you'll figure it out using my source as example, everyone has to learn the language of angels some day). + - Share your test idea's and I will add it in the list on this page. + - Infrastructure / networking / deployment will be done by me. + + If you contribute: + - You can have a molodetz account with admin rights if you want to repository. I have enough faight in people for such thing, i don't like hierarchy. + +## What is the goal? +Creating a skill test like no one else where everything is allowed instead of the lame "you have to do it this way" tests. We try to test with no bias. It's already a bit biased by using ubuntu / debian containers. I think ubuntu since it's popularity. The tests must be hard, not annoying. diff --git a/io.h b/io.h new file mode 100644 index 0000000..2c9e844 --- /dev/null +++ b/io.h @@ -0,0 +1,84 @@ +#ifndef IO_H +#define IO_H +#include +#include +#include +#include +#include +#include + +int *get_readable(int *fds) +{ + fd_set read_fds; + static int readable[10]; + memset(readable, 0, sizeof(readable)); + FD_ZERO(&read_fds); + int max_fd = -1; + for (int i = 0; fds[i] != -1; i++) + { + FD_SET(fds[i], &read_fds); + if (fds[i] > max_fd) + max_fd = fds[i]; + } + int ready = select(max_fd + 1, &read_fds, NULL, NULL, NULL); + if (ready == -1) + { + perror("select"); + return readable; + } + int readable_index = 0; + readable[readable_index] = -1; + for (int i = 0; fds[i] != -1; i++) + { + if (FD_ISSET(fds[i], &read_fds)) + { + readable[readable_index] = fds[i]; + readable_index++; + readable[readable_index] = -1; + } + } + + return readable; +} + +void msleep(uint time) +{ + usleep(time * 1000); +} + +char *read_line(int fd, size_t limit) +{ + char *buffer = (char *)malloc(limit + 1); + ssize_t length = read(fd, buffer, limit); + if (length > 0) + { + buffer[length] = 0; + return buffer; + } + else if (length == 0) + { + printf("Child process closed"); + } + else + { + perror("read"); + } + return NULL; +} +char *write_str(int fd, char *data) +{ + write(fd, data, strlen(data)); +} + +void type(int fd, char *text) +{ + while (*text) + { + char content[] = {*text, 0}; + write(fd, content, strlen(content)); + text++; + msleep(100); + } +} + +#endif diff --git a/l33t.c b/l33t.c new file mode 100644 index 0000000..7a4223b --- /dev/null +++ b/l33t.c @@ -0,0 +1,50 @@ +#include "io.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include "subprocess.h" +#include "proc.h" +#include "missions/all.h" +#include "state.h" + +int main() +{ + + int pfd = subprocess("bash"); + state_t *state = new_state(pfd, STDIN_FILENO, STDOUT_FILENO); + + // Running a mission is just a one liner! + run_mission(state, vim1); + + char *line; + size_t buffer_size = 1; + int fds[] = {state->pfd, state->ifd, -1}; + while (true) + { + int *readable = get_readable(fds); + int index = 0; + int fd; + while ((fd = readable[index]) != -1) + { + + char *data = read_line(fd, 1024); + + if (fd == state->ifd) + { + + write(pfd, data, strlen(data)); + } + else + { + + printf(data); + } + index++; + } + } +} diff --git a/missions/all.h b/missions/all.h new file mode 100644 index 0000000..bcf8c96 --- /dev/null +++ b/missions/all.h @@ -0,0 +1,3 @@ +#include "vim1.h" + +#include "runner.h" diff --git a/missions/runner.h b/missions/runner.h new file mode 100644 index 0000000..a804704 --- /dev/null +++ b/missions/runner.h @@ -0,0 +1,17 @@ +#include +#include "../state.h" + +pthread_t mission_thread ; + +void run_mission(state_t * state, void * mission(void * data)){ + pthread_create(&mission_thread,NULL, mission,(void *) state); + +} + +void wait_mission(){ + if (pthread_join(mission_thread, NULL) != 0) { + perror("pthread_join"); + exit(EXIT_FAILURE); + } + +} diff --git a/missions/vim1.h b/missions/vim1.h new file mode 100644 index 0000000..18d9df9 --- /dev/null +++ b/missions/vim1.h @@ -0,0 +1,11 @@ +#include "../proc.h" +#include "../state.h" +#include "../io.h" + +void vim1(void * data) { + printf("Open nano\n"); + state_t * state = (state_t *)data; + wait_new_process("vim"); + type(state->pfd, "iWell done!"); + fflush(stdout); +} diff --git a/proc.h b/proc.h new file mode 100644 index 0000000..6d65beb --- /dev/null +++ b/proc.h @@ -0,0 +1,48 @@ +#ifndef PROC_H +#define PROC_H +#include "subprocess.h" +#include "io.h" +#include "str.h" +#include +#include + +#define PROC_UPDATE_DELAY_MS 200 + + +int process_count(char * name){ + char command[1024] = {0}; + command[0] = 0; + strcpy(command,"ps aux"); + FILE * pipe = popen(command, "r"); + if(pipe == NULL){ + perror("popen"); + exit(EXIT_FAILURE); + } + char buffer[1024*1024] = {0}; + int count = 0; + while(fgets(buffer,sizeof(buffer), pipe) != NULL){ + if(count_word_occurences(buffer,name)) + count++; + } + int status = pclose(pipe); + if(status == -1){ + perror("pclose"); + } + return count; + //WEXITSTATUS(status) +} + +void wait_for_process_count(char * name, uint count){ + while(process_count(name) != count){ + msleep(PROC_UPDATE_DELAY_MS); + } +} + +void wait_new_process(char * name){ + int original_process_count = process_count(name); + while(process_count(name) < original_process_count + 1){ + msleep(PROC_UPDATE_DELAY_MS); + } +} + +#endif diff --git a/state.h b/state.h new file mode 100644 index 0000000..f86f937 --- /dev/null +++ b/state.h @@ -0,0 +1,23 @@ +#ifndef STATE_H +#define STATE_H + +#include + + +typedef struct state_t { + int pfd; + int ifd; + int ofd; +} state_t; + + +state_t * new_state(int pfd, int ifd, int ofd){ + state_t * state = (state_t *)malloc(sizeof(state_t)); + state->pfd = pfd; + state->ifd = ifd; + state->ofd = ofd; + return state; + +} + +#endif diff --git a/str.h b/str.h new file mode 100644 index 0000000..c3320c5 --- /dev/null +++ b/str.h @@ -0,0 +1,17 @@ +#ifndef STR_H +#define STR_H +#include +#include + +uint count_word_occurences(char * content, char *word){ + uint count = 0; + char * found = NULL; + while((found = strstr(content,word)) != NULL){ + count++; + content = found; + content++; + } + return count; +} + +#endif diff --git a/subprocess.h b/subprocess.h new file mode 100644 index 0000000..3e486cf --- /dev/null +++ b/subprocess.h @@ -0,0 +1,48 @@ +#ifndef SUBPROCESS_H +#define SUBPROCESS_H + +#include +#include +#include +#include +#include +#include + +pid_t pid = NULL; + +int subprocess(char *command) +{ + int sp[2] = {0}; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == -1) + { + perror("socketpair"); + exit(EXIT_FAILURE); + } + + pid = fork(); + + if (pid == -1) + { + perror("fork"); + exit(EXIT_FAILURE); + } + + if (!pid) + { + close(sp[0]); + dup2(sp[1], STDIN_FILENO); + dup2(sp[1], STDOUT_FILENO); + dup2(sp[1], STDERR_FILENO); + close(sp[1]); + execlp(command, command, NULL); + perror("execlp"); + exit(EXIT_FAILURE); + } + else + { + close(sp[1]); + return sp[0]; + } +} +#endif