Hacktober 2019 - Filesystems
I recently finished the Hacktober 2019 CTF from the great folks @UVUCSC. The challenges were mostly entry-level but there were a few that were quite challenging.
The highest-point-value challenge was a frustrating and time-consuming monster developed by my friend chuck called filesystems
. I was the only solver of the challenge and was asked to do a write up of it, and because it was such a twisted and annoying challenge (that I learned a lot from) I decided to go ahead and do it.
Which means, I have to solve it all over again.
chuck-sigh
Unfortunately I haven’t figure out out how to display images on my hugo-templated website yet, so you’ll have to follow along on the command line and use your imagination if you want to see what happened.
Anyway, let’s get started.
For this challenge we aren’t given anything but a tar
file called challenge1.tar
. Extracting it traditionally gives us the following directory tree:
./
├── challenge1.img
├── header/
│ ├── folder0/
│ │ ├── file0
│ │ ├── file1
│ │ ├── file2
│ │ ├── file3
│ │ ├── file4
│ │ ├── file5
│ │ ├── file6
│ │ ├── file7
│ │ ├── file8
│ │ └── file9
│ ├── folder1/
│ │ ├── file0
│ │ ├── file1
│ │ ├── file2
│ │ ├── file3
│ │ ├── file4
│ │ ├── file5
│ │ ├── file6
│ │ ├── file7
│ │ ├── file8
│ │ └── file9
│ ├── folder2/
│ │ ├── file0
│ │ ├── file1
│ │ ├── file2
│ │ ├── file3
│ │ ├── file4
│ │ ├── file5
│ │ ├── file6
│ │ ├── file7
│ │ ├── file8
│ │ └── file9
│ ├── folder3/
│ │ ├── file0
│ │ ├── file1
│ │ ├── file2
│ │ ├── file3
│ │ ├── file4
│ │ ├── file5
│ │ ├── file6
│ │ ├── file7
│ │ ├── file8
│ │ └── file9
│ ├── folder4/
│ │ ├── file0
│ │ ├── file1
│ │ ├── file2
│ │ ├── file3
│ │ ├── file4
│ │ ├── file5
│ │ ├── file6
│ │ ├── file7
│ │ ├── file8
│ │ └── file9
│ ├── folder5/
│ │ ├── file0
│ │ ├── file1
│ │ ├── file2
│ │ ├── file3
│ │ ├── file4
│ │ ├── file5
│ │ ├── file6
│ │ ├── file7
│ │ ├── file8
│ │ └── file9
│ ├── folder6/
│ │ ├── file0
│ │ ├── file1
│ │ ├── file2
│ │ ├── file3
│ │ ├── file4
│ │ ├── file5
│ │ ├── file6
│ │ ├── file7
│ │ ├── file8
│ │ └── file9
│ ├── folder7/
│ │ ├── file0
│ │ ├── file1
│ │ ├── file2
│ │ ├── file3
│ │ ├── file4
│ │ ├── file5
│ │ ├── file6
│ │ ├── file7
│ │ ├── file8
│ │ └── file9
│ ├── folder8/
│ │ ├── file0
│ │ ├── file1
│ │ ├── file2
│ │ ├── file3
│ │ ├── file4
│ │ ├── file5
│ │ ├── file6
│ │ ├── file7
│ │ ├── file8
│ │ └── file9
│ └── folder9/
│ ├── file0
│ ├── file1
│ ├── file2
│ ├── file3
│ ├── file4
│ ├── file5
│ ├── file6
│ ├── file7
│ ├── file8
│ └── file9
└── key/
├── folder0/
│ ├── file0
│ ├── file1
│ ├── file10
│ ├── file11
│ ├── file12
│ ├── file13
│ ├── file14
│ ├── file15
│ ├── file16
│ ├── file17
│ ├── file18
│ ├── file19
│ ├── file2
│ ├── file20
│ ├── file21
│ ├── file22
│ ├── file23
│ ├── file24
│ ├── file25
│ ├── file26
│ ├── file27
│ ├── file28
│ ├── file29
│ ├── file3
│ ├── file30
│ ├── file31
│ ├── file32
│ ├── file33
│ ├── file34
│ ├── file35
│ ├── file36
│ ├── file37
│ ├── file38
│ ├── file39
│ ├── file4
│ ├── file40
│ ├── file41
│ ├── file42
│ ├── file43
│ ├── file44
│ ├── file45
│ ├── file46
│ ├── file47
│ ├── file48
│ ├── file49
│ ├── file5
│ ├── file50
│ ├── file51
│ ├── file52
│ ├── file53
│ ├── file54
│ ├── file55
│ ├── file56
│ ├── file57
│ ├── file58
│ ├── file59
│ ├── file6
│ ├── file60
│ ├── file61
│ ├── file62
│ ├── file63
│ ├── file64
│ ├── file65
│ ├── file66
│ ├── file67
│ ├── file68
│ ├── file69
│ ├── file7
│ ├── file70
│ ├── file71
│ ├── file72
│ ├── file73
│ ├── file74
│ ├── file75
│ ├── file76
│ ├── file77
│ ├── file78
│ ├── file79
│ ├── file8
│ ├── file80
│ ├── file81
│ ├── file82
│ ├── file83
│ ├── file84
│ ├── file85
│ ├── file86
│ ├── file87
│ ├── file88
│ ├── file89
│ ├── file9
│ ├── file90
│ ├── file91
│ ├── file92
│ ├── file93
│ ├── file94
│ ├── file95
│ ├── file96
│ ├── file97
│ ├── file98
│ └── file99
├── folder1/
│ ├── file0
│ ├── file1
│ ├── file10
│ ├── file11
│ ├── file12
│ ├── file13
│ ├── file14
│ ├── file15
│ ├── file16
│ ├── file17
│ ├── file18
│ ├── file19
│ ├── file2
│ ├── file20
│ ├── file21
│ ├── file22
│ ├── file23
│ ├── file24
│ ├── file25
│ ├── file26
│ ├── file27
│ ├── file28
│ ├── file29
│ ├── file3
│ ├── file30
│ ├── file31
│ ├── file32
│ ├── file33
│ ├── file34
│ ├── file35
│ ├── file36
│ ├── file37
│ ├── file38
│ ├── file39
│ ├── file4
│ ├── file40
│ ├── file41
│ ├── file42
│ ├── file43
│ ├── file44
│ ├── file45
│ ├── file46
│ ├── file47
│ ├── file48
│ ├── file49
│ ├── file5
│ ├── file50
│ ├── file51
│ ├── file52
│ ├── file53
│ ├── file54
│ ├── file55
│ ├── file56
│ ├── file57
│ ├── file58
│ ├── file59
│ ├── file6
│ ├── file60
│ ├── file61
│ ├── file62
│ ├── file63
│ ├── file64
│ ├── file65
│ ├── file66
│ ├── file67
│ ├── file68
│ ├── file69
│ ├── file7
│ ├── file70
│ ├── file71
│ ├── file72
│ ├── file73
│ ├── file74
│ ├── file75
│ ├── file76
│ ├── file77
│ ├── file78
│ ├── file79
│ ├── file8
│ ├── file80
│ ├── file81
│ ├── file82
│ ├── file83
│ ├── file84
│ ├── file85
│ ├── file86
│ ├── file87
│ ├── file88
│ ├── file89
│ ├── file9
│ ├── file90
│ ├── file91
│ ├── file92
│ ├── file93
│ ├── file94
│ ├── file95
│ ├── file96
│ ├── file97
│ ├── file98
│ └── file99
├── folder2/
│ ├── file0
│ ├── file1
│ ├── file10
│ ├── file11
│ ├── file12
│ ├── file13
│ ├── file14
│ ├── file15
│ ├── file16
│ ├── file17
│ ├── file18
│ ├── file19
│ ├── file2
│ ├── file20
│ ├── file21
│ ├── file22
│ ├── file23
│ ├── file24
│ ├── file25
│ ├── file26
│ ├── file27
│ ├── file28
│ ├── file29
│ ├── file3
│ ├── file30
│ ├── file31
│ ├── file32
│ ├── file33
│ ├── file34
│ ├── file35
│ ├── file36
│ ├── file37
│ ├── file38
│ ├── file39
│ ├── file4
│ ├── file40
│ ├── file41
│ ├── file42
│ ├── file43
│ ├── file44
│ ├── file45
│ ├── file46
│ ├── file47
│ ├── file48
│ ├── file49
│ ├── file5
│ ├── file50
│ ├── file51
│ ├── file52
│ ├── file53
│ ├── file54
│ ├── file55
│ ├── file56
│ ├── file57
│ ├── file58
│ ├── file59
│ ├── file6
│ ├── file60
│ ├── file61
│ ├── file62
│ ├── file63
│ ├── file64
│ ├── file65
│ ├── file66
│ ├── file67
│ ├── file68
│ ├── file69
│ ├── file7
│ ├── file70
│ ├── file71
│ ├── file72
│ ├── file73
│ ├── file74
│ ├── file75
│ ├── file76
│ ├── file77
│ ├── file78
│ ├── file79
│ ├── file8
│ ├── file80
│ ├── file81
│ ├── file82
│ ├── file83
│ ├── file84
│ ├── file85
│ ├── file86
│ ├── file87
│ ├── file88
│ ├── file89
│ ├── file9
│ ├── file90
│ ├── file91
│ ├── file92
│ ├── file93
│ ├── file94
│ ├── file95
│ ├── file96
│ ├── file97
│ ├── file98
│ └── file99
├── folder3/
│ ├── file0
│ ├── file1
│ ├── file10
│ ├── file11
│ ├── file12
│ ├── file13
│ ├── file14
│ ├── file15
│ ├── file16
│ ├── file17
│ ├── file18
│ ├── file19
│ ├── file2
│ ├── file20
│ ├── file21
│ ├── file22
│ ├── file23
│ ├── file24
│ ├── file25
│ ├── file26
│ ├── file27
│ ├── file28
│ ├── file29
│ ├── file3
│ ├── file30
│ ├── file31
│ ├── file32
│ ├── file33
│ ├── file34
│ ├── file35
│ ├── file36
│ ├── file37
│ ├── file38
│ ├── file39
│ ├── file4
│ ├── file40
│ ├── file41
│ ├── file42
│ ├── file43
│ ├── file44
│ ├── file45
│ ├── file46
│ ├── file47
│ ├── file48
│ ├── file49
│ ├── file5
│ ├── file50
│ ├── file51
│ ├── file52
│ ├── file53
│ ├── file54
│ ├── file55
│ ├── file56
│ ├── file57
│ ├── file58
│ ├── file59
│ ├── file6
│ ├── file60
│ ├── file61
│ ├── file62
│ ├── file63
│ ├── file64
│ ├── file65
│ ├── file66
│ ├── file67
│ ├── file68
│ ├── file69
│ ├── file7
│ ├── file70
│ ├── file71
│ ├── file72
│ ├── file73
│ ├── file74
│ ├── file75
│ ├── file76
│ ├── file77
│ ├── file78
│ ├── file79
│ ├── file8
│ ├── file80
│ ├── file81
│ ├── file82
│ ├── file83
│ ├── file84
│ ├── file85
│ ├── file86
│ ├── file87
│ ├── file88
│ ├── file89
│ ├── file9
│ ├── file90
│ ├── file91
│ ├── file92
│ ├── file93
│ ├── file94
│ ├── file95
│ ├── file96
│ ├── file97
│ ├── file98
│ └── file99
├── folder4/
│ ├── file0
│ ├── file1
│ ├── file10
│ ├── file11
│ ├── file12
│ ├── file13
│ ├── file14
│ ├── file15
│ ├── file16
│ ├── file17
│ ├── file18
│ ├── file19
│ ├── file2
│ ├── file20
│ ├── file21
│ ├── file22
│ ├── file23
│ ├── file24
│ ├── file25
│ ├── file26
│ ├── file27
│ ├── file28
│ ├── file29
│ ├── file3
│ ├── file30
│ ├── file31
│ ├── file32
│ ├── file33
│ ├── file34
│ ├── file35
│ ├── file36
│ ├── file37
│ ├── file38
│ ├── file39
│ ├── file4
│ ├── file40
│ ├── file41
│ ├── file42
│ ├── file43
│ ├── file44
│ ├── file45
│ ├── file46
│ ├── file47
│ ├── file48
│ ├── file49
│ ├── file5
│ ├── file50
│ ├── file51
│ ├── file52
│ ├── file53
│ ├── file54
│ ├── file55
│ ├── file56
│ ├── file57
│ ├── file58
│ ├── file59
│ ├── file6
│ ├── file60
│ ├── file61
│ ├── file62
│ ├── file63
│ ├── file64
│ ├── file65
│ ├── file66
│ ├── file67
│ ├── file68
│ ├── file69
│ ├── file7
│ ├── file70
│ ├── file71
│ ├── file72
│ ├── file73
│ ├── file74
│ ├── file75
│ ├── file76
│ ├── file77
│ ├── file78
│ ├── file79
│ ├── file8
│ ├── file80
│ ├── file81
│ ├── file82
│ ├── file83
│ ├── file84
│ ├── file85
│ ├── file86
│ ├── file87
│ ├── file88
│ ├── file89
│ ├── file9
│ ├── file90
│ ├── file91
│ ├── file92
│ ├── file93
│ ├── file94
│ ├── file95
│ ├── file96
│ ├── file97
│ ├── file98
│ └── file99
├── folder5/
│ ├── file0
│ ├── file1
│ ├── file10
│ ├── file11
│ ├── file12
│ ├── file13
│ ├── file14
│ ├── file15
│ ├── file16
│ ├── file17
│ ├── file18
│ ├── file19
│ ├── file2
│ ├── file20
│ ├── file21
│ ├── file22
│ ├── file23
│ ├── file24
│ ├── file25
│ ├── file26
│ ├── file27
│ ├── file28
│ ├── file29
│ ├── file3
│ ├── file30
│ ├── file31
│ ├── file32
│ ├── file33
│ ├── file34
│ ├── file35
│ ├── file36
│ ├── file37
│ ├── file38
│ ├── file39
│ ├── file4
│ ├── file40
│ ├── file41
│ ├── file42
│ ├── file43
│ ├── file44
│ ├── file45
│ ├── file46
│ ├── file47
│ ├── file48
│ ├── file49
│ ├── file5
│ ├── file50
│ ├── file51
│ ├── file52
│ ├── file53
│ ├── file54
│ ├── file55
│ ├── file56
│ ├── file57
│ ├── file58
│ ├── file59
│ ├── file6
│ ├── file60
│ ├── file61
│ ├── file62
│ ├── file63
│ ├── file64
│ ├── file65
│ ├── file66
│ ├── file67
│ ├── file68
│ ├── file69
│ ├── file7
│ ├── file70
│ ├── file71
│ ├── file72
│ ├── file73
│ ├── file74
│ ├── file75
│ ├── file76
│ ├── file77
│ ├── file78
│ ├── file79
│ ├── file8
│ ├── file80
│ ├── file81
│ ├── file82
│ ├── file83
│ ├── file84
│ ├── file85
│ ├── file86
│ ├── file87
│ ├── file88
│ ├── file89
│ ├── file9
│ ├── file90
│ ├── file91
│ ├── file92
│ ├── file93
│ ├── file94
│ ├── file95
│ ├── file96
│ ├── file97
│ ├── file98
│ └── file99
├── folder6/
│ ├── file0
│ ├── file1
│ ├── file10
│ ├── file11
│ ├── file12
│ ├── file13
│ ├── file14
│ ├── file15
│ ├── file16
│ ├── file17
│ ├── file18
│ ├── file19
│ ├── file2
│ ├── file20
│ ├── file21
│ ├── file22
│ ├── file23
│ ├── file24
│ ├── file25
│ ├── file26
│ ├── file27
│ ├── file28
│ ├── file29
│ ├── file3
│ ├── file30
│ ├── file31
│ ├── file32
│ ├── file33
│ ├── file34
│ ├── file35
│ ├── file36
│ ├── file37
│ ├── file38
│ ├── file39
│ ├── file4
│ ├── file40
│ ├── file41
│ ├── file42
│ ├── file43
│ ├── file44
│ ├── file45
│ ├── file46
│ ├── file47
│ ├── file48
│ ├── file49
│ ├── file5
│ ├── file50
│ ├── file51
│ ├── file52
│ ├── file53
│ ├── file54
│ ├── file55
│ ├── file56
│ ├── file57
│ ├── file58
│ ├── file59
│ ├── file6
│ ├── file60
│ ├── file61
│ ├── file62
│ ├── file63
│ ├── file64
│ ├── file65
│ ├── file66
│ ├── file67
│ ├── file68
│ ├── file69
│ ├── file7
│ ├── file70
│ ├── file71
│ ├── file72
│ ├── file73
│ ├── file74
│ ├── file75
│ ├── file76
│ ├── file77
│ ├── file78
│ ├── file79
│ ├── file8
│ ├── file80
│ ├── file81
│ ├── file82
│ ├── file83
│ ├── file84
│ ├── file85
│ ├── file86
│ ├── file87
│ ├── file88
│ ├── file89
│ ├── file9
│ ├── file90
│ ├── file91
│ ├── file92
│ ├── file93
│ ├── file94
│ ├── file95
│ ├── file96
│ ├── file97
│ ├── file98
│ └── file99
├── folder7/
│ ├── file0
│ ├── file1
│ ├── file10
│ ├── file11
│ ├── file12
│ ├── file13
│ ├── file14
│ ├── file15
│ ├── file16
│ ├── file17
│ ├── file18
│ ├── file19
│ ├── file2
│ ├── file20
│ ├── file21
│ ├── file22
│ ├── file23
│ ├── file24
│ ├── file25
│ ├── file26
│ ├── file27
│ ├── file28
│ ├── file29
│ ├── file3
│ ├── file30
│ ├── file31
│ ├── file32
│ ├── file33
│ ├── file34
│ ├── file35
│ ├── file36
│ ├── file37
│ ├── file38
│ ├── file39
│ ├── file4
│ ├── file40
│ ├── file41
│ ├── file42
│ ├── file43
│ ├── file44
│ ├── file45
│ ├── file46
│ ├── file47
│ ├── file48
│ ├── file49
│ ├── file5
│ ├── file50
│ ├── file51
│ ├── file52
│ ├── file53
│ ├── file54
│ ├── file55
│ ├── file56
│ ├── file57
│ ├── file58
│ ├── file59
│ ├── file6
│ ├── file60
│ ├── file61
│ ├── file62
│ ├── file63
│ ├── file64
│ ├── file65
│ ├── file66
│ ├── file67
│ ├── file68
│ ├── file69
│ ├── file7
│ ├── file70
│ ├── file71
│ ├── file72
│ ├── file73
│ ├── file74
│ ├── file75
│ ├── file76
│ ├── file77
│ ├── file78
│ ├── file79
│ ├── file8
│ ├── file80
│ ├── file81
│ ├── file82
│ ├── file83
│ ├── file84
│ ├── file85
│ ├── file86
│ ├── file87
│ ├── file88
│ ├── file89
│ ├── file9
│ ├── file90
│ ├── file91
│ ├── file92
│ ├── file93
│ ├── file94
│ ├── file95
│ ├── file96
│ ├── file97
│ ├── file98
│ └── file99
├── folder8/
│ ├── file0
│ ├── file1
│ ├── file10
│ ├── file11
│ ├── file12
│ ├── file13
│ ├── file14
│ ├── file15
│ ├── file16
│ ├── file17
│ ├── file18
│ ├── file19
│ ├── file2
│ ├── file20
│ ├── file21
│ ├── file22
│ ├── file23
│ ├── file24
│ ├── file25
│ ├── file26
│ ├── file27
│ ├── file28
│ ├── file29
│ ├── file3
│ ├── file30
│ ├── file31
│ ├── file32
│ ├── file33
│ ├── file34
│ ├── file35
│ ├── file36
│ ├── file37
│ ├── file38
│ ├── file39
│ ├── file4
│ ├── file40
│ ├── file41
│ ├── file42
│ ├── file43
│ ├── file44
│ ├── file45
│ ├── file46
│ ├── file47
│ ├── file48
│ ├── file49
│ ├── file5
│ ├── file50
│ ├── file51
│ ├── file52
│ ├── file53
│ ├── file54
│ ├── file55
│ ├── file56
│ ├── file57
│ ├── file58
│ ├── file59
│ ├── file6
│ ├── file60
│ ├── file61
│ ├── file62
│ ├── file63
│ ├── file64
│ ├── file65
│ ├── file66
│ ├── file67
│ ├── file68
│ ├── file69
│ ├── file7
│ ├── file70
│ ├── file71
│ ├── file72
│ ├── file73
│ ├── file74
│ ├── file75
│ ├── file76
│ ├── file77
│ ├── file78
│ ├── file79
│ ├── file8
│ ├── file80
│ ├── file81
│ ├── file82
│ ├── file83
│ ├── file84
│ ├── file85
│ ├── file86
│ ├── file87
│ ├── file88
│ ├── file89
│ ├── file9
│ ├── file90
│ ├── file91
│ ├── file92
│ ├── file93
│ ├── file94
│ ├── file95
│ ├── file96
│ ├── file97
│ ├── file98
│ └── file99
└── folder9/
├── file0
├── file1
├── file10
├── file11
├── file12
├── file13
├── file14
├── file15
├── file16
├── file17
├── file18
├── file19
├── file2
├── file20
├── file21
├── file22
├── file23
├── file24
├── file25
├── file26
├── file27
├── file28
├── file29
├── file3
├── file30
├── file31
├── file32
├── file33
├── file34
├── file35
├── file36
├── file37
├── file38
├── file39
├── file4
├── file40
├── file41
├── file42
├── file43
├── file44
├── file45
├── file46
├── file47
├── file48
├── file49
├── file5
├── file50
├── file51
├── file52
├── file53
├── file54
├── file55
├── file56
├── file57
├── file58
├── file59
├── file6
├── file60
├── file61
├── file62
├── file63
├── file64
├── file65
├── file66
├── file67
├── file68
├── file69
├── file7
├── file70
├── file71
├── file72
├── file73
├── file74
├── file75
├── file76
├── file77
├── file78
├── file79
├── file8
├── file80
├── file81
├── file82
├── file83
├── file84
├── file85
├── file86
├── file87
├── file88
├── file89
├── file9
├── file90
├── file91
├── file92
├── file93
├── file94
├── file95
├── file96
├── file97
├── file98
└── file99
So we’re only one step into this and we’re already ready for a tl;dr. Well here it is. Let’s take a look at the content of one of the files:
$> xxd key/folder0/file5 | head -n 10
00000000: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000010: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000020: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000060: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000070: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000080: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
And guess what guys? It goes on for another million bytes like that! The whole thing, just all zeros. And it’s not the only one! After sampling files all over that horrible tree all I’m seeing is zeros. Megabytes and megabytes of null, all over my hard drive. Thanks chuck!
We also have this challenge1.img file, which the diskarbitration framework on my mac doesn’t recognize and neither does file
:
$> file challenge1.img
challenge1.img: data
Great. Well I’ll look at the image in a hexdump as well but won’t see anything useful. All we have is a file of keys and headers, and so let’s start googling there.
A quick google search for header key disk image
(the three things we seem to have) one of the entries about 5 down is
“Bruteforcing Linux Full Disk Encryption (LUKS) With Hashcat”
Linux Full Disk Encryption? LUKS? What the crap is that? Let us google further:
The Linux Unified Key Setup (LUKS) is a disk encryption specification created by Clemens Fruhwirth in 2004 and was originally intended for Linux. While most disk encryption software implements different, incompatible, and undocumented formats, LUKS implements a platform-independent standard on-disk format for use in various tools.
I know that chuck really likes Linux, in fact he runs it on his laptop. Maybe this is what we’re looking for? Let’s see if key and header have anything to do with LUKS. After googling luks key header
we find this site which quotes the following:
Following up our LUKS installation, we will go further and explore how to add a backup passphrase as well as how to backup and restore LUKS volume header in case of disaster. LUKS format uses a metadata header and 8 key-slot areas that are being placed at the beginning of the disk. The passphrases are used to decrypt a single master key that is stored in the anti-forensic stripes.
That sounds like the type of data that we have! But what about all these blank files? Let’s go through all of them and compare the hashes of the empty ones and see if any aren’t all zeros:
$> for file in $(ls key/*/*); do md5 $file; done
...
MD5 (key/folder3/file81) = b6d81b360a5672d80c27430f39153e2c
MD5 (key/folder3/file82) = b6d81b360a5672d80c27430f39153e2c
MD5 (key/folder3/file83) = b6d81b360a5672d80c27430f39153e2c
MD5 (key/folder3/file84) = 5a447860f291d664316a344562e14a30
MD5 (key/folder3/file85) = b6d81b360a5672d80c27430f39153e2c
MD5 (key/folder3/file86) = b6d81b360a5672d80c27430f39153e2c
MD5 (key/folder3/file87) = b6d81b360a5672d80c27430f39153e2c
...
Aha! Did you see it? Only one file in the keys isn’t all zeros! Lets copy that out (key/folder3/file84). What about the header files?
$> for file in $(ls header/*/*); do md5 $file; done
...
MD5 (header/folder6/file5) = 2c7ab85a893283e98c931e9511add182
MD5 (header/folder6/file6) = 2c7ab85a893283e98c931e9511add182
MD5 (header/folder6/file7) = 2c7ab85a893283e98c931e9511add182
MD5 (header/folder6/file8) = 213b661636a402ff256d8807e8bb7372
MD5 (header/folder6/file9) = 2c7ab85a893283e98c931e9511add182
MD5 (header/folder7/file0) = 2c7ab85a893283e98c931e9511add182
MD5 (header/folder7/file1) = 2c7ab85a893283e98c931e9511add182
...
Eureka! (does anyone say that anymore??) We have only one file in the headers file that isn’t all zeros. We’ll copy it out too (header/folder6/file8).
So now that we have just one header and one key, we should have enough data to decrypt the disk image (if it is a LUKS image that is).
Unfortunately that means it is time to move over to Linux to try this out. Fortunately it’s just a VM that I can fire up. For this challenge I used a vanilla Ubuntu 18.04 box.
Now I don’t know anything about LUKS, so it’s time to do a bit of research. The site I posted above seems to do a pretty good job of explaining what we need to do to “restore” the LUKS header to our “damaged” image:
$> cryptsetup luksHeaderRestore <device> --header-backup-file <file>
So let’s try it out. After copying the challenge1.img, file8 and file84 to the linux VM, we try it out:
$> cryptsetup luksHeaderRestore challenge1.img --header-backup-file file8
Doing so we are given this handy little warning:
WARNING!
========
Device challenge1.img does not contain LUKS header. Replacing header can destroy data on that device.
Are you sure? (Type uppercase yes):
This makes sense to me, because I’m thinking that if the image does indeed contain a luks header, we would have gotten something out of file
indicating that it was a LUKS system. What we want to do is put the LUKS header in place, then decrypt the volume with the corresponding key.
YES
I probably should have backed up that file before irreversibly modifying it… oh well.
If we run file
on challenge1.img now we get:
challenge1.img: LUKS encrypted file, ver 1 [aes, xts-plain64, sha256] UUID: c3c465b4-4a78-4215-975e-f8ac6c8350ea
Ok, so now we have to decrypt it and mount any file systems on it… I think. After digging through the man
page for cryptsetup
I learn the following:
luksOpen <device> <name> (old syntax)
Opens the LUKS device <device> and sets up a mapping <name> after successful verification of the supplied passphrase.
First, the passphrase is searched in LUKS tokens. If it's not found in any token and also the passphrase is not supplied via --key-file, the command prompts for it interactively.
<options> can be [--key-file, --keyfile-offset, --keyfile-size, --readonly, --test-passphrase, --allow-discards, --header, --key-slot, --master-key-file, --token-id, --token-only, --dis‐
able-keyring, --disable-locks].
What I understand from this is that this command should provide us a decrypted device at <name>
if we give it a valid keyfile and cooresponding LUKS device, which we should have. That’s a lot of should’s. We’ll see if this works.
$> sudo cryptsetup luksOpen challenge1.img challenge1_decrypted --key-file file84
Ok, it says it worked, but now what? Some more googling later I learn that a mapping generated by LUKS is stored in /dev/mapper/
, and looking there sure enough:
$> ls /dev/mapper/
challenge1_decrypted control
Is this it? Did we do it? Did we create a decrypted device?? Let’s try mounting it:
$> sudo mkdir /mnt/challenge1
$> sudo mount /dev/mapper/challenge1_decrypted /mnt/challenge1
$>
It worked! No errors! Let’s cd
to that directory and get our flag!
$> cd /mnt/challenge1/ && ls
$>
Uh, what?
$> ls -la
total 4
drwxr-xr-x 1 vagrant vagrant 0 Oct 2 17:42 .
drwxr-xr-x 3 root root 4096 Oct 29 16:18 ..
There’s nothing in there! It’s empty! We came all this way… after all this work…
At this point I’m kindof feeling like this but I refuse to give up! There has to be something!
In frustration I call mount
, which ends in the following line:
/dev/mapper/challenge1_decrypted on /mnt/challenge1 type btrfs (rw,relatime,space_cache,subvolid=256,subvol=/default)
Two things catch my eye here. The first is that the filesystem type is btrfs, which is something I have heard chuck talk about several times. The second thing I notice is the options used to mount the volume include subvolid
and subvol
. Time to google BTRFS.
* …Much reading later… *
A subvolume is a part of filesystem with its own and independent file/directory hierarchy. Subvolumes can share file extents. A snapshot is also subvolume, but with a given initial content of the original subvolume. Note: A subvolume in btrfs is not like an LVM logical volume, which is block-level snapshot while btrfs subvolumes are file extent-based.
So BTRFS has the notion of subvolumes which are kindof just nested volumes like ZFS or LVM, but different. They use extents (contiguous blocks of storage) to define their subvolumes. Does this BTRFS have other subvolumes perhaps?
A little bit of googling later I learn that there is a btrfs
command that will let you view the subvolumes on a btrfs filesystem:
$> sudo btrfs subvolume list /mnt/challenge1
ID 256 gen 17 top level 5 path default
ID 257 gen 13 top level 5 path non-default
Ok, now we’re getting somewhere! There’s a non-default
subvolume on our btrfs filesystem that we didn’t see before. A quick google of “how to mount btrfs subvlume” takes me here, where I learn the command to change the default subvolume that is mounted when a btrfs filesystem is mounted:
$> btrfs subvolume set-default 257 /mnt/challenge1/
(257 is the subvolume ID). Now we unmount and remount the volume:
$> sudo umount /mnt/challenge1
$> sudo mount /dev/mapper/challenge1_decrypted /mnt/challenge1
Now we see if there is anything inside:
ls -la /mnt/challenge1/
total 8
drwxr-xr-x 1 vagrant vagrant 32 Oct 2 17:44 .
drwxr-xr-x 4 root root 4096 Oct 29 17:35 ..
-rwxrwxrwx 1 vagrant vagrant 220 Oct 2 17:09 instructions.rar
Halleluja! We’ve finally reached the end and found our flag! Let’s extract that tar file:
$> cd /mnt/challenge1/ && tar -xvf instructions.rar
tar: This does not look like a tar archive
tar: Exiting with failure status due to previous errors
* Looks carefully *
tar: This does not look like a tar archive
** Looks more carefully **
instructions.rar
A .rar file?? Who uses rar files anymore?? Ok then, this shouldn’t be too difficult, just got to install rar
and uncompress it…
$> sudo apt install rar
Reading package lists... Done
Building dependency tree
Reading state information... Done
Suggested packages:
unrar
The following NEW packages will be installed:
rar
0 upgraded, 1 newly installed, 0 to remove and 94 not upgraded.
Need to get 295 kB of archives.
After this operation, 799 kB of additional disk space will be used.
Get:1 http://us.archive.ubuntu.com/ubuntu bionic/multiverse amd64 rar amd64 2:5.5.0-1 [295 kB]
Fetched 295 kB in 1s (511 kB/s)
Selecting previously unselected package rar.
(Reading database ... 88083 files and directories currently installed.)
Preparing to unpack .../rar_2%3a5.5.0-1_amd64.deb ...
Unpacking rar (2:5.5.0-1) ...
Setting up rar (2:5.5.0-1) ...
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...
$> rar e instructions.rar
RAR 5.50 Copyright (c) 1993-2017 Alexander Roshal 11 Aug 2017
Trial version Type 'rar -?' for help
Extracting from instructions.rar
Extracting instructions.txt OK
All OK
Alright, we have our instructions.txt
, which isn’t as nice as the flag, but still something! Let’s see what our final step is:
$> cat instructions.txt
The flag is not here.
What? That’s it?? That’s all you have for me Chuck, after all this work??? Maybe I’m missing some unprintable characters, let’s see a hexdump of the file:
$> xxd instructions.txt
00000000: 5468 6520 666c 6167 2069 7320 6e6f 7420 The flag is not
00000010: 6865 7265 2e here.
Nope! All 21 bytes are right there for me to see, nothing is hidden.
:face_with_raised_eyebrow: emoji here.
So this seems a lot like our previous problem, where initially we didn’t see anything, but then we found out that the technology was capable of hiding things in plain sight. Let’s take a step back and see if the rar command can hide additional files that we’re not seeing.
* 15 minutes of reading later *
It doesn’t look like it. Everything in rar is pretty up front, which means this text file really is all we get. But this can’t be a dead end! Chuck would not be that cruel!
So let’s take another step back and look at the rar file. Putting it through a hexdump we see this:
$> xxd instructions.rar
00000000: 5261 7221 1a07 0100 3392 b5e5 0a01 0506 Rar!....3.......
00000010: 0005 0101 8080 00b3 43d8 b72c 0203 0b95 ........C..,....
00000020: 0004 9500 2050 346a 9480 0000 1069 6e73 .... P4j.....ins
00000030: 7472 7563 7469 6f6e 732e 7478 740a 0302 tructions.txt...
00000040: 377e b62a 7679 d501 5468 6520 666c 6167 7~.*vy..The flag
00000050: 2069 7320 6e6f 7420 6865 7265 2e96 1977 is not here...w
00000060: 8d27 0323 11cb 8000 04c9 8000 0064 45bc .'.#.........dE.
00000070: 6780 0300 0353 544d 1007 3a6e 6f74 7468 g....STM..:notth
00000080: 6566 6c61 672e 7478 74c7 d548 3530 333f eflag.txt..H503?
00000090: 7504 2ef9 2c07 c04b 2cba d903 93eb 71c0 u...,..K,.....q.
000000a0: 3cb1 f651 0be0 d349 8a7c 9785 b3ea 79f2 <..Q...I.|....y.
000000b0: ddc4 3621 363b 1428 8be4 585e 6632 9923 ..6!6;.(..X^f2.#
000000c0: be82 4c46 da72 08b2 a860 1b4d 4f88 0aa9 ..LF.r...`.MO...
000000d0: d7ff ae78 1d77 5651 0305 0400 ...x.wVQ....
So ignoring as much unreadable binary as we can, we go from the top and see that we have a rar file… it’s got a file called instructions.txt it looks like, the contents say “The flag is not here” (haha, very cheeky)… but wait! What is this? nottheflag.txt
?? Where does that come from? How do I read it’s contents?
I go back through the documentation for rar
but can find absolutely nothing about hidden files in the format. Everything about the file comes out with that command, but obviously there is more to the story here. There are 220 bytes in this rar file, and I have a feeling that we’ll need to go through the rar file specification one byte at a time to see how we get it out.
So that’s exactly what I’m going to do.
IS THIS WHAT YOU WANTED, CHUCK? YOU WANTED ME TO READ A FILE BYTE BY BYTE AND COMPARE IT TO THE SPECIFICATION??
Byte. After. Byte. We go through the version signature. Through the RAR header. One file, but a length longer than 21 bytes. Finally we get to byte 118 and we see STM..:nottheflag.txt
. And this, my friends, is where we find our next clue:
(From the above specification:)
For service header this field contains a name of service header. Now the following names are used: CMT Archive comment QO Archive quick open data ACL NTFS file permissions STM NTFS alternate data stream RR Recovery record
That’s what it is, some new alien technology defined by the STM service header: an NTFS alternate data stream.
WTH is an NTFS alternate data stream? Our friend Robert at Microsoft explains profoundly:
It is a data stream that is alternate.
That makes so much more sense now! Thanks Robert from Microsoft!
Annoyed, I continue reading the article with a sinking realization that this part will require a Windows VM of me.
chuck-sigh
I fire up and install Windows in a VM because believe it or not, I don’t have any reason to keep one handy.
This takes some time, and after paying my dues to the devil and letting Windows Telemetry play big brother on the VM, I finally have Windows machine to move this rar file over to.
So we install WinRAR and go through the process of extracting the instructions.txt file to the desktop.
Now it’s up to our friend Robert from Microsoft to help us view this alternate NTFS stream in Powershell. This part I can do from a command line!
PS C:\> Get-item -Path C:\Users\cronocide\Desktop\instructions\instructions.txt -stream *
PSPath : Microsoft.PowerShell.Core\FileSystem::C:\Users\Cronocide\Desktop\instructions\instructions.txt::$DATA
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\Users\Cronocide\Desktop\instructions
PSChildName : instructions.txt::$DATA
PSDrive : C
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName : C:\Users\Cronocide\Desktop\instructions\instructions.txt
Stream : :$DATA
Length : 21
PSPath : Microsoft.PowerShell.Core\FileSystem::C:\Users\Cronocide\Desktop\instructions\instructions.txt:notthefl
ag.txt
PSParentPath : Microsoft.PowerShell.Core\FileSystem::C:\Users\Cronocide\Desktop\instructions
PSChildName : instructions.txt:nottheflag.txt
PSDrive : C
PSProvider : Microsoft.PowerShell.Core\FileSystem
PSIsContainer : False
FileName : C:\Users\Cronocide\Desktop\instructions\instructions.txt
Stream : nottheflag.txt
Length : 73
We can see right there that our ’nottheflag.txt’ is an alternate NTFS stream available to be read from instructions.txt, which can only be read on an NTFS filesystem. Now I know and trust Chuck, despite all of the pain he’s put us through in this challenge, but I don’t believe for a second that nottheflag.txt
isn’t the flag! It’s got to be! There’s nowhere else to go! There’s nothing else to do! The game has to be over!
Finally, we read the alternate stream:
PS C:\Users\Cronocide> Get-content -Path C:\Users\Cronocide\Desktop\instructions\instructions.txt -stream nottheflag.txt
flag{b2d31d31a8c453a8ee263c3dffe6a689271f93307d81e0bb141c7c814e1339c4}
There it is. We found the treasure.
flag{b2d31d31a8c453a8ee263c3dffe6a689271f93307d81e0bb141c7c814e1339c4}
I sit back in my reclining office chair at my desk. It’s dark outside. This challenge took my whole evening.
But it was a good challenge. It was fun. And even though I had to read the rar specification byte by byte, I still learned a ton of cool new stuff.
And at the end of the day, win or lose, that’s what makes it all worth it.
Thanks Chuck, this challenge was awesome.