add hacking blogposts as they are
84
1/0.md
Normal file
|
@ -0,0 +1,84 @@
|
|||
# Binary Exploitation
|
||||
|
||||
## Downloading the binary file
|
||||
|
||||
|
||||
|
||||
|
||||
` ![]()
|
||||
|
||||
## Solution
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
![]()
|
||||
|
||||
![]()
|
||||
|
||||
![]()
|
||||
|
||||
![]()
|
||||
|
||||
![]()
|
||||
|
||||
![]()
|
||||
|
||||
![]()
|
||||
|
||||
![]()
|
||||
|
||||
![]()
|
||||
|
||||
![]()
|
||||
|
||||
![]()
|
||||
|
||||
## Title
|
||||
|
||||
text
|
||||
|
||||
|
||||
|
||||
|
||||
` ![]()
|
||||
|
||||
## Title
|
||||
|
||||
text
|
||||
|
||||
|
||||
|
||||
|
||||
` ![]()
|
||||
|
BIN
1/1.png
Normal file
After Width: | Height: | Size: 111 KiB |
BIN
1/2.png
Normal file
After Width: | Height: | Size: 303 KiB |
BIN
1/3.png
Normal file
After Width: | Height: | Size: 552 KiB |
BIN
1/4.png
Normal file
After Width: | Height: | Size: 780 KiB |
BIN
1/5.png
Normal file
After Width: | Height: | Size: 252 KiB |
BIN
1/6.png
Normal file
After Width: | Height: | Size: 759 KiB |
BIN
1/7.png
Normal file
After Width: | Height: | Size: 454 KiB |
402
1/beleaf.md
Normal file
|
@ -0,0 +1,402 @@
|
|||
# CSAW 2019 Beleaf
|
||||
|
||||
## Downloading the binary file
|
||||
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ wget https://github.com/guyinatuxedo/nightmare/raw/master/modules/03-beginner_re/csaw19_beleaf/beleaf
|
||||
--2021-02-22 19:55:50-- https://github.com/guyinatuxedo/nightmare/raw/master/modules/03-beginner_re/csaw19_beleaf/beleaf
|
||||
Resolving github.com (github.com)... 140.82.121.4
|
||||
Connecting to github.com (github.com)|140.82.121.4|:443... connected.
|
||||
HTTP request sent, awaiting response... 302 Found
|
||||
Location: https://raw.githubusercontent.com/guyinatuxedo/nightmare/master/modules/03-beginner_re/csaw19_beleaf/beleaf [following]
|
||||
--2021-02-22 19:55:51-- https://raw.githubusercontent.com/guyinatuxedo/nightmare/master/modules/03-beginner_re/csaw19_beleaf/beleaf
|
||||
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.110.133, 185.199.108.133, 185.199.111.133, ...
|
||||
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.110.133|:443... connected.
|
||||
HTTP request sent, awaiting response... 200 OK
|
||||
Length: 7624 (7.4K) [application/octet-stream]
|
||||
Saving to: ‘beleaf’
|
||||
|
||||
beleaf 100%[===============================================================================>] 7.45K --.-KB/s in 0.01s
|
||||
|
||||
2021-02-22 19:55:51 (676 KB/s) - ‘beleaf’ saved [7624/7624]
|
||||
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ file beleaf
|
||||
beleaf: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=6d305eed7c9bebbaa60b67403a6c6f2b36de3ca4, stripped
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ chmod +x beleaf
|
||||
|
||||
|
||||
|
||||
` ![]()
|
||||
|
||||
## Solution
|
||||
|
||||
Now, first things first, we are going to use pwntools' pwn tool to check the security of the binary file itself.
|
||||
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ pwn checksec beleaf
|
||||
[*] '/home/nothing/binexp/1/beleaf'
|
||||
Arch: amd64-64-little
|
||||
RELRO: Full RELRO
|
||||
Stack: Canary found
|
||||
NX: NX enabled
|
||||
PIE: PIE enabled
|
||||
|
||||
|
||||
|
||||
So we are dealing with a 64bit binary, that scans the input of the user and then checks it, very much like the previous challenge we solved, [helithumper](heli.html). So we're going to import the file into ghidra, and take a look at the main function
|
||||
|
||||

|
||||
|
||||
Here the main function is not called 'main' like in the previous challenge, to do so i had to look for the 'Enter the flag >>>" print statement which happened to be in the FUN_001008a1 function as you can see in the screenshot above. The code that ghidra gives us says that our text input is called 'local_98' and then later on the length of our text input is passed into sVar1
|
||||
|
||||
|
||||
undefined8 FUN_001008a1(void)
|
||||
|
||||
{
|
||||
size_t sVar1;
|
||||
long lVar2;
|
||||
long in_FS_OFFSET;
|
||||
ulong local_b0;
|
||||
char local_98 [136];
|
||||
long local_10;
|
||||
|
||||
local_10 = *(long *)(in_FS_OFFSET + 0x28);
|
||||
printf("Enter the flag\n>>> ");
|
||||
__isoc99_scanf(&DAT;_00100a78,local_98);
|
||||
sVar1 = strlen(local_98);
|
||||
if (sVar1 < 0x21) {
|
||||
puts("Incorrect!");
|
||||
/* WARNING: Subroutine does not return */
|
||||
exit(1);
|
||||
}
|
||||
local_b0 = 0;
|
||||
while (local_b0 < sVar1) {
|
||||
lVar2 = FUN_001007fa((int)local_98[local_b0]);
|
||||
if (lVar2 != *(long *)(&DAT;_003014e0 + local_b0 * 8)) {
|
||||
puts("Incorrect!");
|
||||
/* WARNING: Subroutine does not return */
|
||||
exit(1);
|
||||
}
|
||||
local_b0 = local_b0 + 1;
|
||||
}
|
||||
puts("Correct!");
|
||||
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
|
||||
/* WARNING: Subroutine does not return */
|
||||
__stack_chk_fail();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
now let's look at what we need to get the 'correct' output, first of all if our input LENGTH (sVar1) is less than 0x21 or 33 bytes, we will get 'incorrect', so we need at least 33 characters:
|
||||
|
||||
|
||||
if (sVar1 < 0x21) {
|
||||
puts("Incorrect!");
|
||||
/* WARNING: Subroutine does not return */
|
||||
exit(1);
|
||||
|
||||
|
||||
Then we see that we enter a for loop (which is a while loop with a variable being incremented (here it is local_b0))
|
||||
|
||||
|
||||
while (local_b0 < sVar1) {
|
||||
lVar2 = FUN_001007fa((int)local_98[local_b0]);
|
||||
if (lVar2 != *(long *)(&DAT;_003014e0 + local_b0 * 8)) {
|
||||
puts("Incorrect!");
|
||||
/* WARNING: Subroutine does not return */
|
||||
exit(1);
|
||||
}
|
||||
local_b0 = local_b0 + 1;
|
||||
}
|
||||
puts("Correct!");
|
||||
|
||||
|
||||
in this for loop, each character of our text input (local_98 at the index 0,1,2,3 ... 32) gets passed into the 'FUN_001007fa' function the result of that function gets passed to the if statement as 'lVar2' to get checked against a certain '&DAT;_003014e0' which is basically an array, the if statement checks for the characters at offsets of 8. So let's double click it to see what it is:
|
||||
|
||||
|
||||
DAT_003014e0 XREF[2]: FUN_001008a1:0010096b(*),
|
||||
FUN_001008a1:00100972(R)
|
||||
003014e0 01 ?? 01h
|
||||
|
||||
003014e1 00 ?? 00h
|
||||
003014e2 00 ?? 00h
|
||||
003014e3 00 ?? 00h
|
||||
003014e4 00 ?? 00h
|
||||
003014e5 00 ?? 00h
|
||||
003014e6 00 ?? 00h
|
||||
003014e7 00 ?? 00h
|
||||
003014e8 09 ?? 09h
|
||||
|
||||
003014e9 00 ?? 00h
|
||||
003014ea 00 ?? 00h
|
||||
003014eb 00 ?? 00h
|
||||
003014ec 00 ?? 00h
|
||||
003014ed 00 ?? 00h
|
||||
003014ee 00 ?? 00h
|
||||
003014ef 00 ?? 00h
|
||||
003014f0 11 ?? 11h
|
||||
|
||||
003014f1 00 ?? 00h
|
||||
003014f2 00 ?? 00h
|
||||
003014f3 00 ?? 00h
|
||||
003014f4 00 ?? 00h
|
||||
003014f5 00 ?? 00h
|
||||
003014f6 00 ?? 00h
|
||||
003014f7 00 ?? 00h
|
||||
003014f8 27 ?? 27h '
|
||||
|
||||
003014f9 00 ?? 00h
|
||||
003014fa 00 ?? 00h
|
||||
003014fb 00 ?? 00h
|
||||
003014fc 00 ?? 00h
|
||||
003014fd 00 ?? 00h
|
||||
003014fe 00 ?? 00h
|
||||
003014ff 00 ?? 00h
|
||||
00301500 02 ?? 02h
|
||||
|
||||
|
||||
|
||||
And here we see the bytes we need are at offsets of 8, so we have the following:
|
||||
|
||||
|
||||
0x1 0x9 0x11 0x27 0x2
|
||||
|
||||
|
||||
Now let's take a look at the 'FUN_001007fa' function that checks each of our input text characters:
|
||||
|
||||

|
||||
|
||||
|
||||
long FUN_001007fa(char param_1)
|
||||
|
||||
{
|
||||
long local_10;
|
||||
|
||||
local_10 = 0;
|
||||
while ((local_10 != -1 && ((int)param_1 != *(int *)(&DAT;_00301020 + local_10 * 4)))) {
|
||||
if ((int)param_1 < *(int *)(&DAT;_00301020 + local_10 * 4)) {
|
||||
local_10 = local_10 * 2 + 1;
|
||||
}
|
||||
else {
|
||||
if (*(int *)(&DAT;_00301020 + local_10 * 4) < (int)param_1) {
|
||||
local_10 = (local_10 + 1) * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return local_10;
|
||||
}
|
||||
|
||||
|
||||
in here, each character of our input text gets passed as the param_1 charcater, and then the function basically looks at the 'DAT_003014e0' array with offsets of 4, the function tries to find at which index our input text characters are in this array, so let's see what is in that 'DAT_003014e0' array
|
||||
|
||||
|
||||
DAT_00301020 XREF[6]: FUN_001007fa:00100820(*),
|
||||
FUN_001007fa:00100827(R),
|
||||
FUN_001007fa:00100844(*),
|
||||
FUN_001007fa:0010084b(R),
|
||||
FUN_001007fa:00100873(*),
|
||||
FUN_001007fa:0010087a(R)
|
||||
00301020 77 ?? 77h w
|
||||
|
||||
00301021 00 ?? 00h
|
||||
00301022 00 ?? 00h
|
||||
00301023 00 ?? 00h
|
||||
00301024 66 ?? 66h f
|
||||
|
||||
00301025 00 ?? 00h
|
||||
00301026 00 ?? 00h
|
||||
00301027 00 ?? 00h
|
||||
00301028 7b ?? 7Bh {
|
||||
|
||||
00301029 00 ?? 00h
|
||||
0030102a 00 ?? 00h
|
||||
0030102b 00 ?? 00h
|
||||
0030102c 5f ?? 5Fh _
|
||||
|
||||
0030102d 00 ?? 00h
|
||||
0030102e 00 ?? 00h
|
||||
0030102f 00 ?? 00h
|
||||
00301030 6e ?? 6Eh n
|
||||
|
||||
00301031 00 ?? 00h
|
||||
00301032 00 ?? 00h
|
||||
00301033 00 ?? 00h
|
||||
00301034 79 ?? 79h y
|
||||
|
||||
00301035 00 ?? 00h
|
||||
00301036 00 ?? 00h
|
||||
00301037 00 ?? 00h
|
||||
00301038 7d ?? 7Dh }
|
||||
|
||||
00301039 00 ?? 00h
|
||||
0030103a 00 ?? 00h
|
||||
0030103b 00 ?? 00h
|
||||
0030103c ff ?? FFh
|
||||
0030103d ff ?? FFh
|
||||
0030103e ff ?? FFh
|
||||
0030103f ff ?? FFh
|
||||
00301040 62 ?? 62h b
|
||||
|
||||
00301041 00 ?? 00h
|
||||
00301042 00 ?? 00h
|
||||
00301043 00 ?? 00h
|
||||
00301044 6c ?? 6Ch l
|
||||
|
||||
00301045 00 ?? 00h
|
||||
00301046 00 ?? 00h
|
||||
00301047 00 ?? 00h
|
||||
00301048 72 ?? 72h r
|
||||
|
||||
00301049 00 ?? 00h
|
||||
0030104a 00 ?? 00h
|
||||
0030104b 00 ?? 00h
|
||||
0030104c ff ?? FFh
|
||||
0030104d ff ?? FFh
|
||||
0030104e ff ?? FFh
|
||||
0030104f ff ?? FFh
|
||||
00301050 ff ?? FFh
|
||||
00301051 ff ?? FFh
|
||||
00301052 ff ?? FFh
|
||||
00301053 ff ?? FFh
|
||||
00301054 ff ?? FFh
|
||||
00301055 ff ?? FFh
|
||||
00301056 ff ?? FFh
|
||||
00301057 ff ?? FFh
|
||||
00301058 ff ?? FFh
|
||||
00301059 ff ?? FFh
|
||||
0030105a ff ?? FFh
|
||||
0030105b ff ?? FFh
|
||||
0030105c ff ?? FFh
|
||||
0030105d ff ?? FFh
|
||||
0030105e ff ?? FFh
|
||||
0030105f ff ?? FFh
|
||||
00301060 ff ?? FFh
|
||||
00301061 ff ?? FFh
|
||||
00301062 ff ?? FFh
|
||||
00301063 ff ?? FFh
|
||||
00301064 61 ?? 61h a
|
||||
|
||||
00301065 00 ?? 00h
|
||||
00301066 00 ?? 00h
|
||||
00301067 00 ?? 00h
|
||||
00301068 65 ?? 65h e
|
||||
|
||||
00301069 00 ?? 00h
|
||||
0030106a 00 ?? 00h
|
||||
0030106b 00 ?? 00h
|
||||
0030106c 69 ?? 69h i
|
||||
[...]
|
||||
|
||||
|
||||
|
||||
now when you look at the characters in this array, you can get the feeling that you might be able to type flag{something} with it, so let's follow what the code does with the 2 arrays we found:
|
||||
|
||||
we know that the start of the 1020array is 00301020. The character f will output 1 because **((0x00301024 - 0x00301020) / 4) = 1** so this is equal to 1. This 1 also corresponds to the 14e0 array from earlier:
|
||||
|
||||
|
||||
DAT_003014e0 XREF[2]: FUN_001008a1:0010096b(*),
|
||||
FUN_001008a1:00100972(R)
|
||||
003014e0 01 ?? 01h
|
||||
|
||||
003014e1 00 ?? 00h
|
||||
003014e2 00 ?? 00h
|
||||
003014e3 00 ?? 00h
|
||||
003014e4 00 ?? 00h
|
||||
003014e5 00 ?? 00h
|
||||
003014e6 00 ?? 00h
|
||||
003014e7 00 ?? 00h
|
||||
003014e8 09 ?? 09h
|
||||
|
||||
003014e9 00 ?? 00h
|
||||
003014ea 00 ?? 00h
|
||||
003014eb 00 ?? 00h
|
||||
003014ec 00 ?? 00h
|
||||
003014ed 00 ?? 00h
|
||||
003014ee 00 ?? 00h
|
||||
003014ef 00 ?? 00h
|
||||
003014f0 11 ?? 11h
|
||||
|
||||
003014f1 00 ?? 00h
|
||||
003014f2 00 ?? 00h
|
||||
003014f3 00 ?? 00h
|
||||
003014f4 00 ?? 00h
|
||||
003014f5 00 ?? 00h
|
||||
003014f6 00 ?? 00h
|
||||
003014f7 00 ?? 00h
|
||||
003014f8 27 ?? 27h '
|
||||
|
||||
003014f9 00 ?? 00h
|
||||
003014fa 00 ?? 00h
|
||||
003014fb 00 ?? 00h
|
||||
003014fc 00 ?? 00h
|
||||
003014fd 00 ?? 00h
|
||||
003014fe 00 ?? 00h
|
||||
003014ff 00 ?? 00h
|
||||
00301500 02 ?? 02h
|
||||
|
||||
[...]
|
||||
|
||||
|
||||
|
||||
and here you have to continue with the 0x9 value,**(0x00301020 + (4*9)) = 0x301044** this address corresponds to the l character
|
||||
|
||||
|
||||
fl
|
||||
|
||||
|
||||
|
||||
11 is the third character **(0x00301020 + (4*11)) = 0x301064** this corresponds to the a character
|
||||
|
||||
|
||||
fla
|
||||
|
||||
|
||||
27 is the fourth character **(0x00301020 + (4*27)) = 0x3010bc** this corresponds to the g character
|
||||
|
||||
|
||||
flag
|
||||
|
||||
|
||||
from here you keep going and you end up with the following:
|
||||
|
||||
|
||||
flag{we_beleaf_in_your_re_future}
|
||||
|
||||
|
||||
|
||||
so just run the binary with the flag to verify it is correct:
|
||||
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ ./beleaf
|
||||
Enter the flag
|
||||
>>> flag{we_beleaf_in_your_re_future}
|
||||
Correct!
|
||||
|
||||
|
||||
|
||||
## Title
|
||||
|
||||
text
|
||||
|
||||
|
||||
|
||||
|
||||
` ![]()
|
||||
|
||||
## Title
|
||||
|
||||
text
|
||||
|
||||
|
||||
|
||||
|
||||
` ![]()
|
||||
|
294
1/heli.md
Normal file
|
@ -0,0 +1,294 @@
|
|||
# Helithumper Reverse Engineering
|
||||
|
||||
## Downloading the binary file
|
||||
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ wget https://github.com/guyinatuxedo/nightmare/raw/master/modules/03-beginner_re/helithumper_re/rev
|
||||
--2021-02-22 17:19:05-- https://github.com/guyinatuxedo/nightmare/raw/master/modules/03-beginner_re/helithumper_re/rev
|
||||
Resolving github.com (github.com)... 140.82.121.4
|
||||
Connecting to github.com (github.com)|140.82.121.4|:443... connected.
|
||||
HTTP request sent, awaiting response... 302 Found
|
||||
Location: https://raw.githubusercontent.com/guyinatuxedo/nightmare/master/modules/03-beginner_re/helithumper_re/rev [following]
|
||||
--2021-02-22 17:19:05-- https://raw.githubusercontent.com/guyinatuxedo/nightmare/master/modules/03-beginner_re/helithumper_re/rev
|
||||
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.110.133, 185.199.111.133, 185.199.108.133, ...
|
||||
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.110.133|:443... connected.
|
||||
HTTP request sent, awaiting response... 200 OK
|
||||
Length: 16704 (16K) [application/octet-stream]
|
||||
Saving to: ‘rev’
|
||||
|
||||
rev 100%[===============================================================================>] 16.31K --.-KB/s in 0s
|
||||
|
||||
2021-02-22 17:19:05 (37.3 MB/s) - ‘rev’ saved [16704/16704]
|
||||
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ file rev
|
||||
rev: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=e4dbcb1281821db359d566c68fea7380aeb27378, for GNU/Linux 3.2.0, not stripped
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ chmod +x rev
|
||||
|
||||
|
||||
|
||||
` ![]()
|
||||
|
||||
## Solution
|
||||
|
||||
Run the binary
|
||||
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ ./rev
|
||||
Welcome to the Salty Spitoon™, How tough are ya?
|
||||
very though
|
||||
Yeah right. Back to Weenie Hut Jr™ with ya
|
||||
|
||||
|
||||
here the binary prints some text, then lets us input our text (here its 'very though') and then prints some text again. It is safe to assume that we will need to type the correct passphrase to get the correct output. So let's inspect the binary file from ghidra:
|
||||
|
||||
 
|
||||
|
||||
now from here we want to check out the main function of our binary file, so go into the symbol tree tab, into functions, into main, and we get the following code:
|
||||
|
||||

|
||||
|
||||
|
||||
bool main(void)
|
||||
|
||||
{
|
||||
int iVar1;
|
||||
void *pvVar2;
|
||||
|
||||
pvVar2 = calloc(0x32,1);
|
||||
puts(&DAT;_00102008);
|
||||
__isoc99_scanf(&DAT;_0010203b,pvVar2);
|
||||
iVar1 = validate(pvVar2);
|
||||
if (iVar1 == 0) {
|
||||
puts(&DAT;_00102050);
|
||||
}
|
||||
else {
|
||||
puts("Right this way...");
|
||||
}
|
||||
return iVar1 == 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
now here we see something, first of all it does a scanf (to prompt for our input) and then moves our text into pvVar2, then, it calls a function called 'validate' and the result of that function gets put into iVar1 which determines if we get a correct answer or not. So let's inspect the 2 possibilities of the if statement:
|
||||
|
||||
|
||||
if (iVar1 == 0) {
|
||||
puts(&DAT;_00102050);
|
||||
}
|
||||
else {
|
||||
puts("Right this way...");
|
||||
}
|
||||
|
||||
|
||||
From ghidra we see that this '&DAT;_00102050' is the string of characters we saw earlier:
|
||||
|
||||

|
||||
|
||||
therefore, we do not want iVar1 to be equal to 0, we want iVar1 to be equal to 1
|
||||
|
||||
So the hint here is, what is being validated ? How is our input being validated ? we inspect the validate function which HAS TO return 1, if we want our iVar1 to be equal to 1:
|
||||
|
||||

|
||||
|
||||
Which gives us the following code:
|
||||
|
||||
|
||||
undefined8 validate(char *param_1)
|
||||
|
||||
{
|
||||
size_t sVar1;
|
||||
undefined8 uVar2;
|
||||
long in_FS_OFFSET;
|
||||
int local_50;
|
||||
int local_48 [4];
|
||||
undefined4 local_38;
|
||||
undefined4 local_34;
|
||||
undefined4 local_30;
|
||||
undefined4 local_2c;
|
||||
undefined4 local_28;
|
||||
undefined4 local_24;
|
||||
undefined4 local_20;
|
||||
undefined4 local_1c;
|
||||
undefined4 local_18;
|
||||
undefined4 local_14;
|
||||
long local_10;
|
||||
|
||||
local_10 = *(long *)(in_FS_OFFSET + 0x28);
|
||||
local_48[0] = 0x66;
|
||||
local_48[1] = 0x6c;
|
||||
local_48[2] = 0x61;
|
||||
local_48[3] = 0x67;
|
||||
local_38 = 0x7b;
|
||||
local_34 = 0x48;
|
||||
local_30 = 0x75;
|
||||
local_2c = 0x43;
|
||||
local_28 = 0x66;
|
||||
local_24 = 0x5f;
|
||||
local_20 = 0x6c;
|
||||
local_1c = 0x41;
|
||||
local_18 = 0x62;
|
||||
local_14 = 0x7d;
|
||||
sVar1 = strlen(param_1);
|
||||
local_50 = 0;
|
||||
do {
|
||||
if ((int)sVar1 <= local_50) {
|
||||
uVar2 = 1;
|
||||
LAB_001012b7:
|
||||
if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
|
||||
/* WARNING: Subroutine does not return */
|
||||
__stack_chk_fail();
|
||||
}
|
||||
return uVar2;
|
||||
}
|
||||
if ((int)param_1[local_50] != local_48[local_50]) {
|
||||
uVar2 = 0;
|
||||
goto LAB_001012b7;
|
||||
}
|
||||
local_50 = local_50 + 1;
|
||||
} while( true );
|
||||
}
|
||||
|
||||
|
||||
So first of all our input text gets passed into the validate function via the param_1 parameter. It enters a do{} while(); loop, with each iteration of that while loop, there is a value that gets incremented, the only return statements of that function are either return uVar2 or either not making the function return anything at all, instead going to the __stack_chk_fail() function. therefore the important value here is uVar2
|
||||
|
||||
|
||||
int local_48 [4];
|
||||
|
||||
[...]
|
||||
|
||||
local_48[0] = 0x66;
|
||||
local_48[1] = 0x6c;
|
||||
local_48[2] = 0x61;
|
||||
local_48[3] = 0x67;
|
||||
|
||||
[...]
|
||||
|
||||
if ((int)param_1[local_50] != local_48[local_50]) {
|
||||
uVar2 = 0;
|
||||
goto LAB_001012b7;
|
||||
}
|
||||
local_50 = local_50 + 1;
|
||||
|
||||
|
||||
Here we see that our each character of our input (param1) gets checked against the corresponding character of the local_48 string. Therefore we need to make sure our input matches the values inside of local_48's 0,1,2,3 characters. so we know we have to look at the following addresses:
|
||||
|
||||
|
||||
0x66
|
||||
0x6c
|
||||
0x61
|
||||
0x67
|
||||
|
||||
|
||||
|
||||
From Ghidra, we see the following assembly code:
|
||||
|
||||
|
||||
00101205 c7 45 c0 MOV dword ptr [RBP + local_48],0x66
|
||||
66 00 00 00
|
||||
0010120c c7 45 c4 MOV dword ptr [RBP + local_44],0x6c
|
||||
6c 00 00 00
|
||||
00101213 c7 45 c8 MOV dword ptr [RBP + local_40],0x61
|
||||
61 00 00 00
|
||||
0010121a c7 45 cc MOV dword ptr [RBP + local_3c],0x67
|
||||
67 00 00 00
|
||||
|
||||
|
||||
|
||||
|
||||
00101221 c7 45 d0 MOV dword ptr [RBP + local_38],0x7b
|
||||
7b 00 00 00
|
||||
00101228 c7 45 d4 MOV dword ptr [RBP + local_34],0x48
|
||||
48 00 00 00
|
||||
0010122f c7 45 d8 MOV dword ptr [RBP + local_30],0x75
|
||||
75 00 00 00
|
||||
00101236 c7 45 dc MOV dword ptr [RBP + local_2c],0x43
|
||||
43 00 00 00
|
||||
0010123d c7 45 e0 MOV dword ptr [RBP + local_28],0x66
|
||||
66 00 00 00
|
||||
00101244 c7 45 e4 MOV dword ptr [RBP + local_24],0x5f
|
||||
5f 00 00 00
|
||||
0010124b c7 45 e8 MOV dword ptr [RBP + local_20],0x6c
|
||||
6c 00 00 00
|
||||
00101252 c7 45 ec MOV dword ptr [RBP + local_1c],0x41
|
||||
41 00 00 00
|
||||
00101259 c7 45 f0 MOV dword ptr [RBP + local_18],0x62
|
||||
62 00 00 00
|
||||
00101260 c7 45 f4 MOV dword ptr [RBP + local_14],0x7d
|
||||
7d 00 00 00
|
||||
|
||||
|
||||
Now from here we can get the list of specific bytes our input needs to be:
|
||||
|
||||
|
||||
0x66
|
||||
0x6c
|
||||
0x61
|
||||
0x67
|
||||
|
||||
0x7b
|
||||
0x48
|
||||
0x75
|
||||
0x43
|
||||
0x66
|
||||
0x5f
|
||||
0x6c
|
||||
0x41
|
||||
0x62
|
||||
0x7d
|
||||
|
||||
|
||||
Now let's move over to python:
|
||||
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ ls -lash
|
||||
total 788K
|
||||
4.0K drwxr-xr-x 2 nothing nothing 4.0K Feb 22 17:19 .
|
||||
4.0K drwxr-xr-x 4 nothing nothing 4.0K Feb 22 17:23 ..
|
||||
20K -rwxr-xr-x 1 nothing nothing 17K Feb 22 17:19 rev
|
||||
760K -rwxr-xr-x 1 nothing nothing 759K Feb 22 17:12 strings
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ file rev
|
||||
rev: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=e4dbcb1281821db359d566c68fea7380aeb27378, for GNU/Linux 3.2.0, not stripped
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ python3
|
||||
Python 3.9.1+ (default, Feb 5 2021, 13:46:56)
|
||||
[GCC 10.2.1 20210110] on linux
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
>>> x = [0x66, 0x6c, 0x61, 0x67, 0x7b, 0x48, 0x75, 0x43, 0x66, 0x5f, 0x6c, 0x41, 0x62, 0x7d]
|
||||
>>> input = ""
|
||||
>>> for i in x:
|
||||
... input += chr(i)
|
||||
...
|
||||
>>> input
|
||||
'flag{HuCf_lAb}'
|
||||
|
||||
|
||||
And here we see that the first 4 addresses were 'flag' the next 10 were '{HuCf_lAb}', this obviously was fairly easy
|
||||
|
||||
## Title
|
||||
|
||||
text
|
||||
|
||||
|
||||
|
||||
|
||||
` ![]()
|
||||
|
||||
## Title
|
||||
|
||||
text
|
||||
|
||||
|
||||
|
||||
|
||||
` ![]()
|
||||
|
75
1/strings.md
Normal file
|
@ -0,0 +1,75 @@
|
|||
# Binary Exploitation
|
||||
|
||||
## Downloading the binary file
|
||||
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ wget https://github.com/guyinatuxedo/nightmare/raw/master/modules/03-beginner_re/pico18_strings/strings
|
||||
--2021-02-22 17:12:22-- https://github.com/guyinatuxedo/nightmare/raw/master/modules/03-beginner_re/pico18_strings/strings
|
||||
Resolving github.com (github.com)... 140.82.121.3
|
||||
Connecting to github.com (github.com)|140.82.121.3|:443... connected.
|
||||
HTTP request sent, awaiting response... 302 Found
|
||||
Location: https://raw.githubusercontent.com/guyinatuxedo/nightmare/master/modules/03-beginner_re/pico18_strings/strings [following]
|
||||
--2021-02-22 17:12:22-- https://raw.githubusercontent.com/guyinatuxedo/nightmare/master/modules/03-beginner_re/pico18_strings/strings
|
||||
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 185.199.111.133, 185.199.108.133, 185.199.109.133, ...
|
||||
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|185.199.111.133|:443... connected.
|
||||
HTTP request sent, awaiting response... 200 OK
|
||||
Length: 776368 (758K) [application/octet-stream]
|
||||
Saving to: ‘strings’
|
||||
|
||||
strings 100%[=======================================================================================================================================================================================================>] 758.17K --.-KB/s in 0.1s
|
||||
|
||||
2021-02-22 17:12:23 (5.86 MB/s) - ‘strings’ saved [776368/776368]
|
||||
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ file strings
|
||||
strings: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=e337b489c47492dd5dff90353eb227b4e7e69028, not stripped
|
||||
|
||||
|
||||
` ![]()
|
||||
|
||||
## Solution
|
||||
|
||||
The solution is fairly simple, first make the binary file executable, then run it:
|
||||
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ chmod +x strings
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/2 ] [~/binexp/1]
|
||||
→ ./strings
|
||||
Have you ever used the 'strings' function? Check out the man pages!
|
||||
|
||||
|
||||
Here we are hinted at using the strings function, so we will do so and use grep to try and see if the flag appears, generally the flag contains {flaghash} so we can use grep to find it :
|
||||
|
||||
|
||||
[ 192.168.100.126/24 ] [ /dev/pts/1 ] [~/binexp/1]
|
||||
→ strings strings | grep {
|
||||
picoCTF{sTrIngS_sAVeS_Time_3f712a28}
|
||||
|
||||
|
||||
|
||||
And we're done!
|
||||
|
||||
![]()
|
||||
|
||||
## Title
|
||||
|
||||
text
|
||||
|
||||
|
||||
|
||||
|
||||
` ![]()
|
||||
|
||||
## Title
|
||||
|
||||
text
|
||||
|
||||
|
||||
|
||||
|
||||
` ![]()
|
||||
|