|
22 | 22 | "- **FileUpload** (*TCA-0202-0203 - File Upload*)\n", |
23 | 23 | "- **FileDownload** (*TCA-0201 - File Download*)\n", |
24 | 24 | "- **ReanalyzeFile** (*TCA-0205 - Re-Analyze File*)\n", |
| 25 | + "- **FileReputation** (*TCA-0101 - File Reputation (single query)*)\n", |
| 26 | + "- **FileReputationOverride** (*TCA-0102 - File Reputation Override*)\n", |
25 | 27 | "- **DeleteFile** (*TCA-0204 - Delete File*)\n", |
26 | 28 | "\n", |
27 | 29 | "### Credentials\n", |
|
41 | 43 | }, |
42 | 44 | { |
43 | 45 | "cell_type": "code", |
44 | | - "execution_count": 2, |
45 | | - "metadata": { |
46 | | - "ExecuteTime": { |
47 | | - "end_time": "2024-06-24T13:00:18.771975493Z", |
48 | | - "start_time": "2024-06-24T13:00:18.731201662Z" |
49 | | - } |
50 | | - }, |
| 46 | + "execution_count": null, |
| 47 | + "metadata": {}, |
51 | 48 | "outputs": [], |
52 | 49 | "source": [ |
53 | | - "from ReversingLabs.SDK.ticloud import FileUpload, FileDownload, ReanalyzeFile, DeleteFile" |
| 50 | + "from ReversingLabs.SDK.ticloud import FileUpload, FileDownload, ReanalyzeFile, DeleteFile, FileReputationUserOverride, FileReputation, calculate_hash\n", |
| 51 | + "from ReversingLabs.SDK.helper import SHA1, SHA256, MD5" |
54 | 52 | ] |
55 | 53 | }, |
56 | 54 | { |
|
66 | 64 | }, |
67 | 65 | { |
68 | 66 | "cell_type": "code", |
69 | | - "execution_count": 3, |
70 | | - "metadata": { |
71 | | - "ExecuteTime": { |
72 | | - "end_time": "2024-06-24T13:00:25.846033807Z", |
73 | | - "start_time": "2024-06-24T13:00:25.842115172Z" |
74 | | - } |
75 | | - }, |
| 67 | + "execution_count": null, |
| 68 | + "metadata": {}, |
76 | 69 | "outputs": [], |
77 | 70 | "source": [ |
78 | 71 | "import json\n", |
|
99 | 92 | }, |
100 | 93 | { |
101 | 94 | "cell_type": "code", |
102 | | - "execution_count": 4, |
103 | | - "metadata": { |
104 | | - "ExecuteTime": { |
105 | | - "end_time": "2024-06-24T13:01:24.894826465Z", |
106 | | - "start_time": "2024-06-24T13:01:24.346445039Z" |
107 | | - } |
108 | | - }, |
109 | | - "outputs": [ |
110 | | - { |
111 | | - "name": "stdout", |
112 | | - "output_type": "stream", |
113 | | - "text": [ |
114 | | - "200\n" |
115 | | - ] |
116 | | - } |
117 | | - ], |
| 95 | + "execution_count": null, |
| 96 | + "metadata": {}, |
| 97 | + "outputs": [], |
118 | 98 | "source": [ |
119 | | - "FILE_NAME = \"file_name_placeholder\"\n", |
| 99 | + "FILE_NAME = \"README.md\"\n", |
120 | 100 | "\n", |
121 | 101 | "file_upload = FileUpload(\n", |
122 | 102 | " host=\"https://data.reversinglabs.com\",\n", |
|
125 | 105 | " user_agent=USER_AGENT\n", |
126 | 106 | ")\n", |
127 | 107 | "\n", |
| 108 | + "with open(FILE_NAME, \"rb\") as sample:\n", |
| 109 | + " sample_md5 = calculate_hash(data_input=sample, hashing_algorithm=MD5)\n", |
| 110 | + " sample.seek(0)\n", |
| 111 | + " sample_sha1 = calculate_hash(data_input=sample, hashing_algorithm=SHA1)\n", |
| 112 | + " sample.seek(0)\n", |
| 113 | + " sample_sha256 = calculate_hash(data_input=sample, hashing_algorithm=SHA256)\n", |
| 114 | + "\n", |
128 | 115 | "upload_response = file_upload.upload_sample_from_path(file_path=FILE_NAME)\n", |
129 | 116 | "\n", |
130 | 117 | "status_code = upload_response.status_code\n", |
131 | | - "print(status_code)" |
| 118 | + "print(status_code)\n", |
| 119 | + "print(\"md5\", sample_md5)\n", |
| 120 | + "print(\"sha1\", sample_sha1)\n", |
| 121 | + "print(\"sha256\", sample_sha256)" |
132 | 122 | ] |
133 | 123 | }, |
134 | 124 | { |
|
154 | 144 | "metadata": {}, |
155 | 145 | "outputs": [], |
156 | 146 | "source": [ |
157 | | - "FILE_HASH = \"sha1_hash_placeholder\"\n", |
| 147 | + "FILE_HASH = \"8e21cde3f269b7f359eb8903a130ab11e060325069e16c0ba1674c141d6c9d01\"\n", |
158 | 148 | "\n", |
159 | 149 | "file_download = FileDownload(\n", |
160 | 150 | " host=\"https://data.reversinglabs.com\",\n", |
|
188 | 178 | }, |
189 | 179 | { |
190 | 180 | "cell_type": "code", |
191 | | - "execution_count": 7, |
192 | | - "metadata": { |
193 | | - "ExecuteTime": { |
194 | | - "end_time": "2024-06-24T13:15:51.128618407Z", |
195 | | - "start_time": "2024-06-24T13:15:51.049367153Z" |
196 | | - } |
197 | | - }, |
198 | | - "outputs": [ |
199 | | - { |
200 | | - "name": "stdout", |
201 | | - "output_type": "stream", |
202 | | - "text": [ |
203 | | - "Sample sent for rescanning\n" |
204 | | - ] |
205 | | - } |
206 | | - ], |
| 181 | + "execution_count": null, |
| 182 | + "metadata": {}, |
| 183 | + "outputs": [], |
207 | 184 | "source": [ |
208 | 185 | "reanalyze = ReanalyzeFile(\n", |
209 | 186 | " host=\"https://data.reversinglabs.com\",\n", |
|
228 | 205 | "`Sample sent for rescanning`\n", |
229 | 206 | "\n", |
230 | 207 | "\n", |
231 | | - "### 6. Delete file\n", |
232 | | - "In case we no longer want a file to be present in the cloud and available for analysis or download, we can delete it.\n", |
233 | | - "To delete a file from the TitaniumCloud, we will use the `DeleteFile` class." |
| 208 | + "### 6. Sample reputation override\n", |
| 209 | + "In case we wish to override the classification provided to a sample by Titanium Cloud we can use the FileReputationUserOverride class to do so.\n", |
| 210 | + "But before we do that let's see if our sample already has an override on its classification." |
234 | 211 | ] |
235 | 212 | }, |
236 | 213 | { |
|
239 | 216 | "metadata": {}, |
240 | 217 | "outputs": [], |
241 | 218 | "source": [ |
242 | | - "delete_file = DeleteFile(\n", |
| 219 | + "file_reputation_override = FileReputationUserOverride(\n", |
243 | 220 | " host=\"https://data.reversinglabs.com\",\n", |
244 | 221 | " username=USERNAME,\n", |
245 | 222 | " password=PASSWORD,\n", |
246 | 223 | " user_agent=USER_AGENT\n", |
247 | | - ")\n", |
248 | | - "\n", |
249 | | - "delete_response = delete_file.delete_samples(sample_hashes=FILE_HASH)\n", |
250 | | - "\n", |
251 | | - "response_text = delete_response.text\n", |
252 | | - "print(response_text)" |
| 224 | + ")" |
253 | 225 | ] |
254 | 226 | }, |
255 | 227 | { |
|
258 | 230 | "collapsed": false |
259 | 231 | }, |
260 | 232 | "source": [ |
261 | | - "Again, we used the same file hash. If our file deletion request was successful, the response text will have a non-empty list called `deleted_hashes`. This list carries the hashes of files that have successfully been deleted with this request." |
| 233 | + "We do this by requesting a collection of all sample hashes of a specific hash type.\n", |
| 234 | + "In this example we use the SHA256 algorithm.\n", |
| 235 | + "We check the first page to see if our sample is present." |
262 | 236 | ] |
263 | 237 | }, |
264 | 238 | { |
265 | 239 | "cell_type": "code", |
266 | | - "execution_count": null, |
267 | 240 | "outputs": [], |
268 | 241 | "source": [ |
269 | 242 | "file_override_response = file_reputation_override.list_active_overrides(\"sha256\")\n", |
270 | | - "print(file_override_response.text)\n", |
| 243 | + "count = len(file_override_response.json()[\"rl\"][\"user_override\"][\"hash_values\"])\n", |
| 244 | + "has_more = \"more\" if file_override_response.json()[\"rl\"][\"user_override\"].get(\"has_next\") else \"no more\"\n", |
| 245 | + "print(f\"Found {count} samples with overridden classification, there are {has_more} such samples\")\n", |
271 | 246 | "is_in = \"in\" if file_override_response.text.find(sample_sha256) != -1 else \"not in\"\n", |
272 | | - "print(\"\")\n", |
273 | 247 | "print(f\"Sample is {is_in} the returned response page\")" |
274 | 248 | ], |
275 | 249 | "metadata": { |
276 | 250 | "collapsed": false |
277 | | - } |
| 251 | + }, |
| 252 | + "execution_count": null |
278 | 253 | }, |
279 | 254 | { |
280 | 255 | "cell_type": "markdown", |
281 | 256 | "source": [ |
282 | | - "Cleaning up the override classification is easy. We do it using the same method as before." |
| 257 | + "Now we will add override the reputation to be malicious.\n", |
| 258 | + "We will then retrieve it from TiCloud and see how our change affects the output." |
283 | 259 | ], |
284 | 260 | "metadata": { |
285 | 261 | "collapsed": false |
286 | 262 | } |
287 | 263 | }, |
288 | 264 | { |
289 | 265 | "cell_type": "code", |
290 | | - "execution_count": null, |
291 | 266 | "outputs": [], |
292 | 267 | "source": [ |
293 | | - "cleanup_response = file_reputation_override.override_classification(\n", |
294 | | - " remove_override=[\n", |
295 | | - " {\n", |
296 | | - " \"md5\": sample_md5,\n", |
297 | | - " \"sha1\": sample_sha1,\n", |
298 | | - " \"sha256\": sample_sha256\n", |
299 | | - " }\n", |
300 | | - " ]\n", |
| 268 | + "file_reputation_override_response = file_reputation_override.override_classification(\n", |
| 269 | + " override_samples=[{\n", |
| 270 | + " \"md5\": sample_md5,\n", |
| 271 | + " \"sha1\": sample_sha1,\n", |
| 272 | + " \"sha256\": sample_sha256,\n", |
| 273 | + " \"status\": \"MALICIOUS\"\n", |
| 274 | + " }]\n", |
301 | 275 | ")\n", |
302 | | - "print(cleanup_response.status_code)\n", |
303 | | - "print(cleanup_response.text)" |
| 276 | + "print(file_reputation_override_response.status_code)\n", |
| 277 | + "print(json.dumps(file_reputation_override_response.json(), indent=1))" |
304 | 278 | ], |
305 | 279 | "metadata": { |
306 | 280 | "collapsed": false |
307 | | - } |
| 281 | + }, |
| 282 | + "execution_count": null |
308 | 283 | }, |
309 | 284 | { |
310 | 285 | "cell_type": "markdown", |
311 | 286 | "source": [ |
312 | | - "### 7. Delete file\n", |
313 | | - "In case we no longer want a file to be present in the cloud and available for analysis or download, we can delete it.\n", |
314 | | - "To delete a file from the TitaniumCloud, we will use the `DeleteFile` class." |
| 287 | + "You might need to give TiCloud a moment to propagate the new classification through the system." |
315 | 288 | ], |
316 | 289 | "metadata": { |
317 | 290 | "collapsed": false |
318 | 291 | } |
319 | 292 | }, |
320 | 293 | { |
321 | 294 | "cell_type": "code", |
322 | | - "execution_count": null, |
323 | 295 | "outputs": [], |
324 | 296 | "source": [ |
325 | | - "delete_file = DeleteFile(\n", |
| 297 | + "file_reputation = FileReputation(\n", |
326 | 298 | " host=\"https://data.reversinglabs.com\",\n", |
327 | 299 | " username=USERNAME,\n", |
328 | 300 | " password=PASSWORD,\n", |
329 | | - " user_agent=USER_AGENT\n", |
| 301 | + " user_agent=USER_AGENT \n", |
330 | 302 | ")\n", |
331 | | - "\n", |
332 | | - "delete_response = delete_file.delete_samples(sample_hashes=FILE_HASH)\n", |
333 | | - "\n", |
334 | | - "response_text = delete_response.text\n", |
335 | | - "print(response_text)" |
| 303 | + "reputation_response = file_reputation.get_file_reputation(sample_sha256)\n", |
| 304 | + "print(reputation_response.status_code)\n", |
| 305 | + "print(json.dumps(reputation_response.json(), indent=1))" |
336 | 306 | ], |
337 | 307 | "metadata": { |
338 | 308 | "collapsed": false |
339 | | - } |
| 309 | + }, |
| 310 | + "execution_count": null |
340 | 311 | }, |
341 | 312 | { |
342 | | - "cell_type": "raw", |
| 313 | + "cell_type": "markdown", |
343 | 314 | "source": [ |
344 | | - "Again, we used the same file hash. If our file deletion request was successful, the response text will have a non-empty list called `deleted_hashes`. This list carries the hashes of files that have successfully been deleted with this request." |
| 315 | + "Cleaning up the classification override is easy. We do it using the same method as before." |
345 | 316 | ], |
346 | 317 | "metadata": { |
347 | 318 | "collapsed": false |
348 | 319 | } |
349 | 320 | }, |
350 | 321 | { |
351 | 322 | "cell_type": "code", |
352 | | - "execution_count": null, |
353 | | - "metadata": {}, |
354 | | - "outputs": [], |
355 | | - "source": [ |
356 | | - "file_override_response = file_reputation_override.list_active_overrides(\"sha256\")\n", |
357 | | - "print(file_override_response.text)\n", |
358 | | - "is_in = \"in\" if file_override_response.text.find(sample_sha256) != -1 else \"not in\"\n", |
359 | | - "print(\"\")\n", |
360 | | - "print(f\"Sample is {is_in} the returned response page\")" |
361 | | - ] |
362 | | - }, |
363 | | - { |
364 | | - "cell_type": "markdown", |
365 | | - "metadata": { |
366 | | - "collapsed": false |
367 | | - }, |
368 | | - "source": [ |
369 | | - "Cleaning up the override classification is easy. We do it using the same method as before." |
370 | | - ] |
371 | | - }, |
372 | | - { |
373 | | - "cell_type": "code", |
374 | | - "execution_count": null, |
375 | | - "metadata": {}, |
376 | 323 | "outputs": [], |
377 | 324 | "source": [ |
378 | 325 | "cleanup_response = file_reputation_override.override_classification(\n", |
379 | | - " remove_override=[\n", |
380 | | - " {\n", |
381 | | - " \"md5\": sample_md5,\n", |
382 | | - " \"sha1\": sample_sha1,\n", |
383 | | - " \"sha256\": sample_sha256\n", |
384 | | - " }\n", |
385 | | - " ]\n", |
| 326 | + " remove_override=[{\n", |
| 327 | + " \"md5\": sample_md5,\n", |
| 328 | + " \"sha1\": sample_sha1,\n", |
| 329 | + " \"sha256\": sample_sha256\n", |
| 330 | + " }]\n", |
386 | 331 | ")\n", |
387 | 332 | "print(cleanup_response.status_code)\n", |
388 | | - "print(cleanup_response.text)" |
389 | | - ] |
390 | | - }, |
391 | | - { |
392 | | - "cell_type": "markdown", |
393 | | - "source": [], |
| 333 | + "print(json.dumps(cleanup_response.json(), indent=1))" |
| 334 | + ], |
394 | 335 | "metadata": { |
395 | 336 | "collapsed": false |
396 | | - } |
| 337 | + }, |
| 338 | + "execution_count": null |
397 | 339 | }, |
398 | 340 | { |
399 | 341 | "cell_type": "markdown", |
400 | | - "metadata": { |
401 | | - "collapsed": false |
402 | | - }, |
403 | 342 | "source": [ |
404 | 343 | "### 7. Delete file\n", |
405 | 344 | "In case we no longer want a file to be present in the cloud and available for analysis or download, we can delete it.\n", |
406 | 345 | "To delete a file from the TitaniumCloud, we will use the `DeleteFile` class." |
407 | | - ] |
| 346 | + ], |
| 347 | + "metadata": { |
| 348 | + "collapsed": false |
| 349 | + } |
408 | 350 | }, |
409 | 351 | { |
410 | 352 | "cell_type": "code", |
411 | | - "execution_count": null, |
412 | | - "metadata": {}, |
413 | 353 | "outputs": [], |
414 | 354 | "source": [ |
415 | 355 | "delete_file = DeleteFile(\n", |
|
423 | 363 | "\n", |
424 | 364 | "response_text = delete_response.text\n", |
425 | 365 | "print(response_text)" |
426 | | - ] |
427 | | - }, |
428 | | - { |
429 | | - "cell_type": "raw", |
| 366 | + ], |
430 | 367 | "metadata": { |
431 | 368 | "collapsed": false |
432 | 369 | }, |
| 370 | + "execution_count": null |
| 371 | + }, |
| 372 | + { |
| 373 | + "cell_type": "raw", |
433 | 374 | "source": [ |
434 | 375 | "Again, we used the same file hash. If our file deletion request was successful, the response text will have a non-empty list called `deleted_hashes`. This list carries the hashes of files that have successfully been deleted with this request." |
435 | | - ] |
| 376 | + ], |
| 377 | + "metadata": { |
| 378 | + "collapsed": false |
| 379 | + } |
436 | 380 | } |
437 | 381 | ], |
438 | 382 | "metadata": { |
|
0 commit comments