|
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