Skip to content

Commit 0e2c2b5

Browse files
Merge pull request #2 from C4T-BuT-S4D/falamous/crypter
add crypter service
2 parents 4f3b584 + 10bd212 commit 0e2c2b5

30 files changed

+1618
-0
lines changed

checkers/crypter/checker.py

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#!/usr/bin/env python3
2+
3+
import random
4+
import secrets
5+
import sys
6+
import uuid
7+
import json
8+
9+
import grpc
10+
from checklib import *
11+
12+
from crypter_lib import CheckMachine
13+
14+
15+
class Checker(BaseChecker):
16+
vulns: int = 1
17+
timeout: int = 15
18+
uses_attack_data: bool = True
19+
20+
def __init__(self, *args, **kwargs):
21+
super(Checker, self).__init__(*args, **kwargs)
22+
self.c = CheckMachine(self)
23+
24+
def action(self, action, *args, **kwargs):
25+
try:
26+
super(Checker, self).action(action, *args, **kwargs)
27+
except self.get_check_finished_exception():
28+
raise
29+
except grpc.RpcError as e:
30+
if e.code() == grpc.StatusCode.UNAVAILABLE:
31+
self.cquit(Status.DOWN, "unavailable", f"grpc error: {e}")
32+
else:
33+
self.cquit(Status.MUMBLE, f"grpc error: {e.code()}", f"grpc error: {e}")
34+
except ConnectionRefusedError:
35+
self.cquit(Status.DOWN, "Connection refused", "Connection refused")
36+
37+
def check(self):
38+
with self.c.connect() as channel, self.c.handle_grpc_error(status=Status.MUMBLE):
39+
stub = self.c.get_stub(channel)
40+
41+
username = rnd_username()
42+
user = self.c.Register(stub, username)
43+
44+
from_username = rnd_username()
45+
from_user = self.c.Register(stub, from_username)
46+
47+
data = rnd_string(32)
48+
message_id = self.c.SendMessage(stub, username, from_user.token, data)
49+
n = self.c.GetUserPublicKey(stub, username)
50+
51+
message = self.c.GetMessage(stub, message_id)
52+
53+
plaintext = self.c.int_to_bytes(self.c.decrypt(user.n, user.lamba, message.encrypted))
54+
55+
self.assert_eq(message.username, username, "incorrect username", Status.MUMBLE)
56+
self.assert_eq(message.from_username, from_username, "incorrect from_username", Status.MUMBLE)
57+
self.assert_eq(plaintext, data.encode(), "incorrect flag", Status.MUMBLE)
58+
59+
self.cquit(Status.OK)
60+
61+
62+
def put(self, flag_id: str, flag: str, vuln: str):
63+
with self.c.connect() as channel, self.c.handle_grpc_error(status=Status.MUMBLE):
64+
stub = self.c.get_stub(channel)
65+
66+
username = rnd_username()
67+
user = self.c.Register(stub, username)
68+
69+
from_username = rnd_username()
70+
from_user = self.c.Register(stub, from_username)
71+
72+
message_id = self.c.SendMessage(stub, username, from_user.token, flag)
73+
self.cquit(Status.OK,
74+
json.dumps({
75+
"message": message_id,
76+
}),
77+
json.dumps({
78+
"username": username,
79+
"lambda": user.lamba,
80+
"from": from_username,
81+
"message": message_id,
82+
}),
83+
)
84+
85+
86+
def get(self, flag_id: str, flag: str, vuln: str):
87+
with self.c.connect() as channel, self.c.handle_grpc_error(status=Status.CORRUPT):
88+
stub = self.c.get_stub(channel)
89+
90+
flag_data = json.loads(flag_id)
91+
92+
lamba = flag_data["lambda"]
93+
username = flag_data["username"]
94+
from_username = flag_data["from"]
95+
message_id = flag_data["message"]
96+
97+
n = self.c.GetUserPublicKey(stub, username)
98+
99+
message = self.c.GetMessage(stub, message_id)
100+
101+
plaintext = self.c.int_to_bytes(self.c.decrypt(n, lamba, message.encrypted))
102+
103+
self.assert_eq(message.username, username, "incorrect username", Status.CORRUPT)
104+
self.assert_eq(message.from_username, from_username, "incorrect from_username", Status.CORRUPT)
105+
self.assert_eq(plaintext, flag.encode(), "incorrect flag", Status.CORRUPT)
106+
107+
self.cquit(Status.OK)
108+
109+
110+
111+
if __name__ == "__main__":
112+
c = Checker(sys.argv[2])
113+
114+
try:
115+
c.action(sys.argv[1], *sys.argv[3:])
116+
except c.get_check_finished_exception():
117+
cquit(Status(c.status), c.public, c.private)

checkers/crypter/crypter_lib.py

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import random
2+
import string
3+
import uuid
4+
from typing import Callable, List, NamedTuple
5+
6+
from checklib import *
7+
import grpc
8+
from contextlib import contextmanager
9+
from crypter_pb2 import (
10+
RegisterRequest,
11+
RegisterResponse,
12+
GetMessageRequest,
13+
GetMessageResponse,
14+
SendMessageRequest,
15+
SendMessageResponse,
16+
GetUserPublicKeyRequest,
17+
GetUserPublicKeyResponse,
18+
)
19+
from crypter_pb2_grpc import CrypterStub
20+
21+
PORT = 2112
22+
23+
class User(NamedTuple):
24+
token: str
25+
n: int
26+
lamba: int
27+
28+
class EncryptedMessage(NamedTuple):
29+
username: string
30+
from_username: string
31+
encrypted: int
32+
33+
class CheckMachine:
34+
def __init__(self, c: BaseChecker):
35+
self.c = c
36+
self.addr = f"{self.c.host}:{PORT}"
37+
38+
def connect(self) -> grpc.Channel:
39+
channel = grpc.insecure_channel(self.addr)
40+
return channel
41+
42+
@staticmethod
43+
def get_stub(channel):
44+
return CrypterStub(channel)
45+
46+
@staticmethod
47+
def Register(
48+
stub: CrypterStub,
49+
username: string
50+
) -> User:
51+
resp: RegisterResponse = stub.Register(
52+
RegisterRequest(
53+
username=username,
54+
)
55+
)
56+
return User(
57+
token=resp.token,
58+
n=int(resp.n),
59+
lamba=int(resp.lamba),
60+
)
61+
62+
@staticmethod
63+
def GetMessage(
64+
stub: CrypterStub,
65+
id: string,
66+
) -> EncryptedMessage:
67+
resp: GetMessageResponse = stub.GetMessage(
68+
GetMessageRequest(
69+
id=id,
70+
)
71+
)
72+
return EncryptedMessage(
73+
username=resp.username,
74+
from_username=resp.from_username,
75+
encrypted=int(resp.encrypted),
76+
)
77+
78+
@staticmethod
79+
def SendMessage(
80+
stub: CrypterStub,
81+
username: string,
82+
token: string,
83+
message: string,
84+
) -> str:
85+
resp: SendMessageResponse = stub.SendMessage(
86+
SendMessageRequest(
87+
username=username,
88+
token=token,
89+
message=message,
90+
)
91+
)
92+
return resp.id
93+
94+
@staticmethod
95+
def GetUserPublicKey(
96+
stub: CrypterStub,
97+
username: string,
98+
) -> str:
99+
resp: GetUserPublicKeyResponse = stub.GetUserPublicKey(
100+
GetUserPublicKeyRequest(
101+
username=username
102+
)
103+
)
104+
return int(resp.n)
105+
106+
@contextmanager
107+
def handle_grpc_error(self, status=Status.MUMBLE):
108+
try:
109+
yield
110+
except grpc.RpcError as e:
111+
if e.code() == grpc.StatusCode.UNAVAILABLE:
112+
raise
113+
else:
114+
self.c.cquit(status, f"grpc error: {e.code()}", f"grpc error: {e}")
115+
except ValueError as e:
116+
self.c.cquit(status, f"value error", f"value error: {e}")
117+
118+
@staticmethod
119+
def fake_flag() -> str:
120+
return (
121+
"B" + rnd_string(31, alphabet=string.ascii_uppercase + string.digits) + "="
122+
)
123+
124+
@staticmethod
125+
def int_to_bytes(n: int) -> bytes:
126+
return n.to_bytes((n.bit_length() + 7 )// 8, "big")
127+
128+
@staticmethod
129+
def decrypt(n: int, lamba: int, e: int):
130+
return (pow(e, lamba, n ** 2) - 1) // n * pow((pow(n + 1, lamba, n ** 2) - 1) // n, -1, n) % n

checkers/crypter/crypter_pb2.py

+56
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

checkers/crypter/crypter_pb2.pyi

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from google.protobuf.internal import containers as _containers
2+
from google.protobuf import descriptor as _descriptor
3+
from google.protobuf import message as _message
4+
from typing import ClassVar as _ClassVar, Iterable as _Iterable, Optional as _Optional
5+
6+
DESCRIPTOR: _descriptor.FileDescriptor
7+
8+
class RegisterRequest(_message.Message):
9+
__slots__ = ("username",)
10+
USERNAME_FIELD_NUMBER: _ClassVar[int]
11+
username: str
12+
def __init__(self, username: _Optional[str] = ...) -> None: ...
13+
14+
class RegisterResponse(_message.Message):
15+
__slots__ = ("token", "n", "lamba")
16+
TOKEN_FIELD_NUMBER: _ClassVar[int]
17+
N_FIELD_NUMBER: _ClassVar[int]
18+
LAMBA_FIELD_NUMBER: _ClassVar[int]
19+
token: str
20+
n: str
21+
lamba: str
22+
def __init__(self, token: _Optional[str] = ..., n: _Optional[str] = ..., lamba: _Optional[str] = ...) -> None: ...
23+
24+
class SendMessageRequest(_message.Message):
25+
__slots__ = ("token", "username", "message")
26+
TOKEN_FIELD_NUMBER: _ClassVar[int]
27+
USERNAME_FIELD_NUMBER: _ClassVar[int]
28+
MESSAGE_FIELD_NUMBER: _ClassVar[int]
29+
token: str
30+
username: str
31+
message: str
32+
def __init__(self, token: _Optional[str] = ..., username: _Optional[str] = ..., message: _Optional[str] = ...) -> None: ...
33+
34+
class SendMessageResponse(_message.Message):
35+
__slots__ = ("id",)
36+
ID_FIELD_NUMBER: _ClassVar[int]
37+
id: str
38+
def __init__(self, id: _Optional[str] = ...) -> None: ...
39+
40+
class ListMessagesRequest(_message.Message):
41+
__slots__ = ("token",)
42+
TOKEN_FIELD_NUMBER: _ClassVar[int]
43+
token: str
44+
def __init__(self, token: _Optional[str] = ...) -> None: ...
45+
46+
class ListMessagesResponse(_message.Message):
47+
__slots__ = ("id",)
48+
ID_FIELD_NUMBER: _ClassVar[int]
49+
id: _containers.RepeatedScalarFieldContainer[str]
50+
def __init__(self, id: _Optional[_Iterable[str]] = ...) -> None: ...
51+
52+
class GetMessageRequest(_message.Message):
53+
__slots__ = ("id",)
54+
ID_FIELD_NUMBER: _ClassVar[int]
55+
id: str
56+
def __init__(self, id: _Optional[str] = ...) -> None: ...
57+
58+
class GetMessageResponse(_message.Message):
59+
__slots__ = ("username", "from_username", "encrypted")
60+
USERNAME_FIELD_NUMBER: _ClassVar[int]
61+
FROM_USERNAME_FIELD_NUMBER: _ClassVar[int]
62+
ENCRYPTED_FIELD_NUMBER: _ClassVar[int]
63+
username: str
64+
from_username: str
65+
encrypted: str
66+
def __init__(self, username: _Optional[str] = ..., from_username: _Optional[str] = ..., encrypted: _Optional[str] = ...) -> None: ...
67+
68+
class GetUserPublicKeyRequest(_message.Message):
69+
__slots__ = ("username",)
70+
USERNAME_FIELD_NUMBER: _ClassVar[int]
71+
username: str
72+
def __init__(self, username: _Optional[str] = ...) -> None: ...
73+
74+
class GetUserPublicKeyResponse(_message.Message):
75+
__slots__ = ("n",)
76+
N_FIELD_NUMBER: _ClassVar[int]
77+
n: str
78+
def __init__(self, n: _Optional[str] = ...) -> None: ...

0 commit comments

Comments
 (0)