Did you know system call number 777 in Linux works as a flag checker?
Attachments:
Main Function
void __fastcall main(__int64 a1, char **a2, char **a3)
{
signed __int64 v3; // rcx
int *v4; // rdi
signed __int64 v5; // rbx
int flag[14]; // [rsp+0h] [rbp-68h]
unsigned __int64 v7; // [rsp+38h] [rbp-30h]
v3 = 14LL;
v7 = __readfsqword(0x28u);
v4 = flag;
while ( v3 )
{
*v4 = 0;
++v4;
--v3;
}
__printf_chk(1LL, "FLAG: ", a3);
if ( (unsigned int)__isoc99_scanf("%55s", flag) == 1 )
{
v5 = 1LL;
do
{
syscall(
777LL,
(unsigned int)flag[v5 - 1],
(unsigned int)flag[(v5 + 0) % 14],
(unsigned int)flag[(v5 + 1) % 14],
(unsigned int)flag[(v5 + 2) % 14]
);
if ( *__errno_location() == 1 )
{
puts("Wrong...");
return;
}
++v5;
}
while ( v5 != 15 );
puts("Correct!");
}
}
- It loops through flag, passes little endian int form of flag bytes at required addresses to syscall
777
- The syscall performs the flag check.
As we know there isn't any 777 syscall, so there must be some SECCOMP filter filtering syscall 777 and adds some functions to it.
unsigned __int64 sub_7C0()
{
char *v0; // rdi
_DWORD *v1; // rsi
__int64 v2; // rcx
__int16 v4; // [rsp+0h] [rbp-688h] BYREF
char *v5; // [rsp+8h] [rbp-680h]
char v6[1640]; // [rsp+10h] [rbp-678h] BYREF
unsigned __int64 v7; // [rsp+678h] [rbp-10h]
v7 = __readfsqword(0x28u);
if ( prctl(38, 1LL, 0LL, 0LL, 0LL) )
goto LABEL_2;
v0 = v6;
v1 = &unk_B00;
v2 = 410LL;
v4 = 205;
while ( v2 )
{
*(_DWORD *)v0 = *v1++;
v0 += 4;
--v2;
}
v5 = v6;
if ( prctl(22, 2LL, &v4) )
LABEL_2:
exit(1);
return __readfsqword(0x28u) ^ v7;
}
So the function adds some SECCOMP filters with prctl
. The function loads a Berkeley Packet Filter, which filters any system calls performed. To analyze the filters I used seccomp-tools to dump the filters.
$ seccomp-tools dump ./chall
Dump File
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000000 A = sys_number
0001: 0x15 0x00 0xc8 0x00000309 if (A != 0x309) goto 0202 ; if syscall number != 777 goto ALLOW
0002: 0x20 0x00 0x00 0x00000010 A = args[0]
0003: 0x54 0x00 0x00 0x000000ff A &= 0xff
0004: 0x35 0xc7 0x00 0x00000080 if (A >= 128) goto 0204 ; if char at 3 of args[0] >= 128 goto ERRNO(1)
0005: 0x20 0x00 0x00 0x00000010 A = args[0]
0006: 0x74 0x00 0x00 0x00000008 A >>= 8
0007: 0x54 0x00 0x00 0x000000ff A &= 0xff
0008: 0x35 0xc3 0x00 0x00000080 if (A >= 128) goto 0204 ; if char at 2 of args[0] >= 128 goto ERRNO(1)
0009: 0x20 0x00 0x00 0x00000010 A = args[0]
0010: 0x74 0x00 0x00 0x00000010 A >>= 16
0011: 0x54 0x00 0x00 0x000000ff A &= 0xff
0012: 0x35 0xbf 0x00 0x00000080 if (A >= 128) goto 0204 ; if char at 1 of args[0] >= 128 goto ERRNO(1)
0013: 0x20 0x00 0x00 0x00000010 A = args[0]
0014: 0x74 0x00 0x00 0x00000018 A >>= 24
0015: 0x54 0x00 0x00 0x000000ff A &= 0xff
0016: 0x35 0xbb 0x00 0x00000080 if (A >= 128) goto 0204 ; if char at 0 of args[0] >= 128 goto ERRNO(1)
0017: 0x20 0x00 0x00 0x00000010 A = args[0]
0018: 0x02 0x00 0x00 0x00000000 mem[0] = A ; mem[0] = args[0]
0019: 0x20 0x00 0x00 0x00000018 A = args[1]
0020: 0x61 0x00 0x00 0x00000000 X = mem[0]
0021: 0xac 0x00 0x00 0x00000000 A ^= X
0022: 0x02 0x00 0x00 0x00000001 mem[1] = A ; mem[1] = mem[0] ^ args[1]
0023: 0x20 0x00 0x00 0x00000020 A = args[2]
0024: 0x61 0x00 0x00 0x00000001 X = mem[1]
0025: 0xac 0x00 0x00 0x00000000 A ^= X
0026: 0x02 0x00 0x00 0x00000002 mem[2] = A ; mem[2] = mem[1] ^ args[2]
0027: 0x20 0x00 0x00 0x00000028 A = args[3]
0028: 0x61 0x00 0x00 0x00000002 X = mem[2]
0029: 0xac 0x00 0x00 0x00000000 A ^= X
0030: 0x02 0x00 0x00 0x00000003 mem[3] = A ; mem[3] = mem[2] ^ args[3]
0031: 0x60 0x00 0x00 0x00000000 A = mem[0]
0032: 0x61 0x00 0x00 0x00000001 X = mem[1]
0033: 0x0c 0x00 0x00 0x00000000 A += X
0034: 0x61 0x00 0x00 0x00000002 X = mem[2]
0035: 0x0c 0x00 0x00 0x00000000 A += X
0036: 0x61 0x00 0x00 0x00000003 X = mem[3]
0037: 0x0c 0x00 0x00 0x00000000 A += X
0038: 0x02 0x00 0x00 0x00000004 mem[4] = A ; mem[4] = mem[0] + mem[1] + mem[2] + mem[3]
0039: 0x60 0x00 0x00 0x00000000 A = mem[0]
0040: 0x61 0x00 0x00 0x00000001 X = mem[1]
0041: 0x1c 0x00 0x00 0x00000000 A -= X
0042: 0x61 0x00 0x00 0x00000002 X = mem[2]
0043: 0x0c 0x00 0x00 0x00000000 A += X
0044: 0x61 0x00 0x00 0x00000003 X = mem[3]
0045: 0x1c 0x00 0x00 0x00000000 A -= X
0046: 0x02 0x00 0x00 0x00000005 mem[5] = A ; mem[5] = mem[0] - mem[1] + mem[2] - mem[3]
0047: 0x60 0x00 0x00 0x00000000 A = mem[0]
0048: 0x61 0x00 0x00 0x00000001 X = mem[1]
0049: 0x0c 0x00 0x00 0x00000000 A += X
0050: 0x61 0x00 0x00 0x00000002 X = mem[2]
0051: 0x1c 0x00 0x00 0x00000000 A -= X
0052: 0x61 0x00 0x00 0x00000003 X = mem[3]
0053: 0x1c 0x00 0x00 0x00000000 A -= X
0054: 0x02 0x00 0x00 0x00000006 mem[6] = A ; mem[6] = mem[0] + mem[1] - mem[2] - mem[3]
0055: 0x60 0x00 0x00 0x00000000 A = mem[0]
0056: 0x61 0x00 0x00 0x00000001 X = mem[1]
0057: 0x1c 0x00 0x00 0x00000000 A -= X
0058: 0x61 0x00 0x00 0x00000002 X = mem[2]
0059: 0x1c 0x00 0x00 0x00000000 A -= X
0060: 0x61 0x00 0x00 0x00000003 X = mem[3]
0061: 0x0c 0x00 0x00 0x00000000 A += X
0062: 0x02 0x00 0x00 0x00000007 mem[7] = A ; mem[7] = mem[0] - mem[1] - mem[2] + mem[3]
0063: 0x60 0x00 0x00 0x00000004 A = mem[4]
0064: 0x61 0x00 0x00 0x00000005 X = mem[5]
0065: 0x4c 0x00 0x00 0x00000000 A |= X
0066: 0x02 0x00 0x00 0x00000008 mem[8] = A ; (mem[4] | mem[5])
0067: 0x60 0x00 0x00 0x00000006 A = mem[6]
0068: 0x61 0x00 0x00 0x00000007 X = mem[7]
0069: 0x5c 0x00 0x00 0x00000000 A &= X
0070: 0x61 0x00 0x00 0x00000008 X = mem[8] ; (mem[6] & mem[7])
0071: 0xac 0x00 0x00 0x00000000 A ^= X
0072: 0x02 0x00 0x00 0x00000008 mem[8] = A ; mem[8] = (mem[6] & mem[7]) ^ (mem[4] | mem[5])
0073: 0x60 0x00 0x00 0x00000005 A = mem[5]
0074: 0x61 0x00 0x00 0x00000006 X = mem[6]
0075: 0x4c 0x00 0x00 0x00000000 A |= X
0076: 0x02 0x00 0x00 0x00000009 mem[9] = A ; (mem[5] | mem[6])
0077: 0x60 0x00 0x00 0x00000007 A = mem[7]
0078: 0x61 0x00 0x00 0x00000004 X = mem[4]
0079: 0x5c 0x00 0x00 0x00000000 A &= X
0080: 0x61 0x00 0x00 0x00000009 X = mem[9] ; (mem[7] & mem[4])
0081: 0xac 0x00 0x00 0x00000000 A ^= X
0082: 0x02 0x00 0x00 0x00000009 mem[9] = A ; mem[9] = (mem[7] & mem[4]) ^ (mem[5] | mem[6])
0083: 0x60 0x00 0x00 0x00000006 A = mem[6]
0084: 0x61 0x00 0x00 0x00000007 X = mem[7]
0085: 0x4c 0x00 0x00 0x00000000 A |= X
0086: 0x02 0x00 0x00 0x0000000a mem[10] = A ; (mem[6] | mem[7])
0087: 0x60 0x00 0x00 0x00000004 A = mem[4]
0088: 0x61 0x00 0x00 0x00000005 X = mem[5]
0089: 0x5c 0x00 0x00 0x00000000 A &= X
0090: 0x61 0x00 0x00 0x0000000a X = mem[10] ; (mem[4] & mem[5])
0091: 0xac 0x00 0x00 0x00000000 A ^= X
0092: 0x02 0x00 0x00 0x0000000a mem[10] = A ; mem[10] = (mem[4] & mem[5]) ^ (mem[6] | mem[7])
0093: 0x60 0x00 0x00 0x00000007 A = mem[7]
0094: 0x61 0x00 0x00 0x00000004 X = mem[4]
0095: 0x4c 0x00 0x00 0x00000000 A |= X
0096: 0x02 0x00 0x00 0x0000000b mem[11] = A ; (mem[7] | mem[4])
0097: 0x60 0x00 0x00 0x00000005 A = mem[5]
0098: 0x61 0x00 0x00 0x00000006 X = mem[6]
0099: 0x5c 0x00 0x00 0x00000000 A &= X
0100: 0x61 0x00 0x00 0x0000000b X = mem[11] ; (mem[5] & mem[6])
0101: 0xac 0x00 0x00 0x00000000 A ^= X
0102: 0x02 0x00 0x00 0x0000000b mem[11] = A ; mem[11] = (mem[5] & mem[6]) ^ (mem[7] | mem[4])
0103: 0x60 0x00 0x00 0x00000008 A = mem[8] ; Checking mem[8]
0104: 0x15 0x25 0x00 0xf5ffc1f6 if (A == 4127179254) goto 0142
0105: 0x15 0x14 0x00 0x7344aeee if (A == 1933881070) goto 0126
0106: 0x15 0x1f 0x00 0xfda6effe if (A == 4255576062) goto 0138
0107: 0x15 0x0a 0x00 0x638f7ca2 if (A == 1670347938) goto 0118
0108: 0x15 0x0f 0x00 0xa2285400 if (A == 2720551936) goto 0124
0109: 0x15 0x1a 0x00 0x8990fefe if (A == 2307981054) goto 0136
0110: 0x15 0x1d 0x00 0x9f576dd4 if (A == 2673307092) goto 0140
0111: 0x15 0x0a 0x00 0xf6b9ebe2 if (A == 4139379682) goto 0122
0112: 0x15 0x0f 0x00 0xf9e28bee if (A == 4192373742) goto 0128
0113: 0x15 0x14 0x00 0x1f9b8fb4 if (A == 530288564) goto 0134
0114: 0x15 0x1d 0x00 0xefec86de if (A == 4025255646) goto 0144
0115: 0x15 0x0e 0x00 0xdf60093a if (A == 3747612986) goto 0130
0116: 0x15 0x03 0x00 0xb8af3fbe if (A == 3098492862) goto 0120
0117: 0x15 0x0e 0x00 0x7f01bbcc if (A == 2130820044) goto 0132
0118: 0x60 0x00 0x00 0x00000009 A = mem[9] ; Checking mem[9]
0119: 0x15 0x32 0x54 0xf1cf5c2e if (A == 4056898606) goto 0170 else goto 0204
0120: 0x60 0x00 0x00 0x00000009 A = mem[9]
0121: 0x15 0x20 0x52 0xb6af7dbe if (A == 3064954302) goto 0154 else goto 0204
0122: 0x60 0x00 0x00 0x00000009 A = mem[9]
0123: 0x15 0x18 0x50 0xd6b9bde2 if (A == 3602496994) goto 0148 else goto 0204
0124: 0x60 0x00 0x00 0x00000009 A = mem[9]
0125: 0x15 0x22 0x4e 0x60fad508 if (A == 1627051272) goto 0160 else goto 0204
0126: 0x60 0x00 0x00 0x00000009 A = mem[9]
0127: 0x15 0x22 0x4c 0x77600ede if (A == 2002783966) goto 0162 else goto 0204
0128: 0x60 0x00 0x00 0x00000009 A = mem[9]
0129: 0x15 0x1c 0x4a 0xf3b68ece if (A == 4088827598) goto 0158 else goto 0204
0130: 0x60 0x00 0x00 0x00000009 A = mem[9]
0131: 0x15 0x24 0x48 0x4fe90926 if (A == 1340672294) goto 0168 else goto 0204
0132: 0x60 0x00 0x00 0x00000009 A = mem[9]
0133: 0x15 0x0c 0x46 0x7e1933ac if (A == 2115580844) goto 0146 else goto 0204
0134: 0x60 0x00 0x00 0x00000009 A = mem[9]
0135: 0x15 0x24 0x44 0x1f9b8fb4 if (A == 530288564) goto 0172 else goto 0204
0136: 0x60 0x00 0x00 0x00000009 A = mem[9]
0137: 0x15 0x1c 0x42 0xcb94e7da if (A == 3415533530) goto 0166 else goto 0204
0138: 0x60 0x00 0x00 0x00000009 A = mem[9]
0139: 0x15 0x0a 0x40 0xb9c2adfe if (A == 3116543486) goto 0150 else goto 0204
0140: 0x60 0x00 0x00 0x00000009 A = mem[9]
0141: 0x15 0x0e 0x3e 0x0f01b94c if (A == 251771212) goto 0156 else goto 0204
0142: 0x60 0x00 0x00 0x00000009 A = mem[9]
0143: 0x15 0x14 0x3c 0xf5efe5f6 if (A == 4126139894) goto 0164 else goto 0204
0144: 0x60 0x00 0x00 0x00000009 A = mem[9]
0145: 0x15 0x06 0x3a 0xa7ad8d4e if (A == 2813168974) goto 0152 else goto 0204
0146: 0x60 0x00 0x00 0x0000000a A = mem[10] ; Checking mem[10]
0147: 0x15 0x2e 0x38 0x7efd33a4 if (A == 2130523044) goto 0194 else goto 0204
0148: 0x60 0x00 0x00 0x0000000a A = mem[10]
0149: 0x15 0x24 0x36 0xd6f33dda if (A == 3606265306) goto 0186 else goto 0204
0150: 0x60 0x00 0x00 0x0000000a A = mem[10]
0151: 0x15 0x26 0x34 0xbbdaa5e6 if (A == 3151668710) goto 0190 else goto 0204
0152: 0x60 0x00 0x00 0x0000000a A = mem[10]
0153: 0x15 0x22 0x32 0x24a7ad2e if (A == 614968622) goto 0188 else goto 0204
0154: 0x60 0x00 0x00 0x0000000a A = mem[10]
0155: 0x15 0x2a 0x30 0xb7fdfcbe if (A == 3086875838) goto 0198 else goto 0204
0156: 0x60 0x00 0x00 0x0000000a A = mem[10]
0157: 0x15 0x10 0x2e 0x0f01b94c if (A == 251771212) goto 0174 else goto 0204
0158: 0x60 0x00 0x00 0x0000000a A = mem[10]
0159: 0x15 0x12 0x2c 0xb3bdaed6 if (A == 3015552726) goto 0178 else goto 0204
0160: 0x60 0x00 0x00 0x0000000a A = mem[10]
0161: 0x15 0x22 0x2a 0x60ffd7bc if (A == 1627379644) goto 0196 else goto 0204
0162: 0x60 0x00 0x00 0x0000000a A = mem[10]
0163: 0x15 0x0c 0x28 0x5f785fd2 if (A == 1601724370) goto 0176 else goto 0204
0164: 0x60 0x00 0x00 0x0000000a A = mem[10]
0165: 0x15 0x12 0x26 0x27aeff3e if (A == 665780030) goto 0184 else goto 0204
0166: 0x60 0x00 0x00 0x0000000a A = mem[10]
0167: 0x15 0x0e 0x24 0xc39dc1ca if (A == 3281895882) goto 0182 else goto 0204
0168: 0x60 0x00 0x00 0x0000000a A = mem[10]
0169: 0x15 0x1e 0x22 0x4d8f1f86 if (A == 1301225350) goto 0200 else goto 0204
0170: 0x60 0x00 0x00 0x0000000a A = mem[10]
0171: 0x15 0x14 0x20 0x99ff4c6e if (A == 2583645294) goto 0192 else goto 0204
0172: 0x60 0x00 0x00 0x0000000a A = mem[10]
0173: 0x15 0x06 0x1e 0xe97d7d54 if (A == 3917315412) goto 0180 else goto 0204
0174: 0x60 0x00 0x00 0x0000000b A = mem[11] ; Checking mem[11]
0175: 0x15 0x1b 0x1c 0x9f576dd4 if (A == 2673307092) goto 0203 else goto 0204
0176: 0x60 0x00 0x00 0x0000000b A = mem[11]
0177: 0x15 0x19 0x1a 0x5b5cffe2 if (A == 1532821474) goto 0203 else goto 0204
0178: 0x60 0x00 0x00 0x0000000b A = mem[11]
0179: 0x15 0x17 0x18 0xb9e9abf6 if (A == 3119098870) goto 0203 else goto 0204
0180: 0x60 0x00 0x00 0x0000000b A = mem[11]
0181: 0x15 0x15 0x16 0xe97d7d54 if (A == 3917315412) goto 0203 else goto 0204
0182: 0x60 0x00 0x00 0x0000000b A = mem[11]
0183: 0x15 0x13 0x14 0x8199d8ee if (A == 2174343406) goto 0203 else goto 0204
0184: 0x60 0x00 0x00 0x0000000b A = mem[11]
0185: 0x15 0x11 0x12 0x27bedb3e if (A == 666819390) goto 0203 else goto 0204
0186: 0x60 0x00 0x00 0x0000000b A = mem[11]
0187: 0x15 0x0f 0x10 0xf6f36bda if (A == 4143147994) goto 0203 else goto 0204
0188: 0x60 0x00 0x00 0x0000000b A = mem[11]
0189: 0x15 0x0d 0x0e 0x6ce6a6be if (A == 1827055294) goto 0203 else goto 0204
0190: 0x60 0x00 0x00 0x0000000b A = mem[11]
0191: 0x15 0x0b 0x0c 0xffbee7e6 if (A == 4290701286) goto 0203 else goto 0204
0192: 0x60 0x00 0x00 0x0000000b A = mem[11]
0193: 0x15 0x09 0x0a 0x0bbf6ce2 if (A == 197094626) goto 0203 else goto 0204
0194: 0x60 0x00 0x00 0x0000000b A = mem[11]
0195: 0x15 0x07 0x08 0x7fe5bbc4 if (A == 2145762244) goto 0203 else goto 0204
0196: 0x60 0x00 0x00 0x0000000b A = mem[11]
0197: 0x15 0x05 0x06 0xa22d56b4 if (A == 2720880308) goto 0203 else goto 0204
0198: 0x60 0x00 0x00 0x0000000b A = mem[11]
0199: 0x15 0x03 0x04 0xb9fdbebe if (A == 3120414398) goto 0203 else goto 0204
0200: 0x60 0x00 0x00 0x0000000b A = mem[11]
0201: 0x15 0x01 0x02 0xdd061f9a if (A == 3708166042) goto 0203 else goto 0204
0202: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0203: 0x06 0x00 0x00 0x00050000 return ERRNO(0)
0204: 0x06 0x00 0x00 0x00050001 return ERRNO(1)
So the following process is done:
mem[0] = arg[0]
mem[1] = mem[0] ^ arg[1]
mem[2] = mem[1] ^ arg[2]
mem[3] = mem[2] ^ arg[3]
mem[4] = mem[0] + mem[1] + mem[2] + mem[3]
mem[5] = mem[0] - mem[1] + mem[2] - mem[3]
mem[6] = mem[0] + mem[1] - mem[2] - mem[3]
mem[7] = mem[0] - mem[1] - mem[2] + mem[3]
mem[8] = (mem[6] & mem[7]) ^ (mem[4] | mem[5])
mem[9] = (mem[7] & mem[4]) ^ (mem[5] | mem[6])
mem[10] = (mem[4] & mem[5]) ^ (mem[6] | mem[7])
mem[11] = (mem[5] & mem[6]) ^ (mem[7] | mem[4])
And the checks of mem[8], mem[9], mem[10], mem[11] are:
mem[8] mem[9] mem[10] mem[11]
----------------------------------------------------------
4127179254 4126139894 665780030 666819390
1933881070 2002783966 1601724370 1532821474
4255576062 3116543486 3151668710 4290701286
1670347938 4056898606 2583645294 197094626
2720551936 1627051272 1627379644 2720880308
2307981054 3415533530 3281895882 2174343406
2673307092 251771212 251771212 2673307092
4139379682 3602496994 3606265306 4143147994
4192373742 4088827598 3015552726 3119098870
530288564 530288564 3917315412 3917315412
4025255646 2813168974 614968622 1827055294
3747612986 1340672294 1301225350 3708166042
3098492862 3064954302 3086875838 3120414398
2130820044 2115580844 2130523044 2145762244
So combining these, made a z3 solver python script.
$ python solve.py
[+] Adding Constraints
[+] Solving
[+] Flag Found >>> zer0pts{B3rk3l3y_P4ck3t_F1lt3r:Y3t_4n0th3r_4ss3mbly}
zer0pts{B3rk3l3y_P4ck3t_F1lt3r:Y3t_4n0th3r_4ss3mbly}