├── README.txt ├── idapomidor.py └── idapomidor └── images ├── flipper00.png ├── flipper01.png ├── flipper02.png ├── flipper10.png ├── flipper11.png ├── flipper12.png ├── flipper20.png ├── flipper21.png ├── flipper22.png ├── flipper30.png ├── flipper31.png ├── flipper32.png ├── flipper40.png ├── flipper41.png ├── flipper42.png ├── flipper50.png ├── flipper51.png ├── flipper52.png ├── flipper60.png ├── flipper61.png ├── flipper62.png ├── flipper70.png ├── flipper71.png ├── flipper72.png ├── flipper80.png ├── flipper81.png ├── flipper82.png ├── flipper90.png ├── flipper91.png ├── flipper92.png ├── pomidor.png └── separator.png /README.txt: -------------------------------------------------------------------------------- 1 | Welcome to IDA Pomidor, a productivity plugin for Hex-Ray's IDA Pro disassembler. 2 | 3 | To install IDA Pomidor simply copy 'idapomidor.py' and 'idapomidor' folder to IDA's plugins folder. The plugin will be automatically loaded the next time you start IDA Pro. 4 | 5 | You can find the latest IDA Pomidor version and documentation here: 6 | http://thesprawl.org/projects/ida-pomidor/ 7 | 8 | Happy reversing! 9 | -Peter Kacherginsky -------------------------------------------------------------------------------- /idapomidor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # IDA Pomidor is a productivity tool that encourages regular timed breaks. 4 | 5 | IDAPOMIDOR_VERSION = "1.0" 6 | 7 | # Copyright (C) 2014 Peter Kacherginsky 8 | # All rights reserved. 9 | # 10 | # Redistribution and use in source and binary forms, with or without 11 | # modification, are permitted provided that the following conditions are met: 12 | # 13 | # 1. Redistributions of source code must retain the above copyright notice, this 14 | # list of conditions and the following disclaimer. 15 | # 2. Redistributions in binary form must reproduce the above copyright notice, 16 | # this list of conditions and the following disclaimer in the documentation 17 | # and/or other materials provided with the distribution. 18 | # 3. Neither the name of the copyright holder nor the names of its contributors 19 | # may be used to endorse or promote products derived from this software without 20 | # specific prior written permission. 21 | # 22 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 23 | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 | # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 26 | # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 | # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 | # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 | # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 | 33 | # Python Libraries 34 | import os 35 | import sys 36 | from datetime import datetime, timedelta 37 | 38 | # IDA libraries 39 | import idaapi 40 | import idautils 41 | import idc 42 | from idaapi import Form, Choose2, plugin_t 43 | 44 | # PySide 45 | try: 46 | from PySide import QtCore, QtGui 47 | except ImportError: 48 | print "[idapomidor] Failed to import PySide library." 49 | print " Please install the library and try again." 50 | sys.exit(1) 51 | 52 | ############################################################################### 53 | # Embeddable history view of previous tasks 54 | class PomidorView(Choose2): 55 | """ 56 | Chooser class to display security characteristics of loaded modules. 57 | """ 58 | def __init__(self, pomidor, embedded = False): 59 | 60 | self.pomidor = pomidor 61 | 62 | Choose2.__init__(self, 63 | "IDA Pomidor", 64 | [ ["Time", 14 | Choose2.CHCOL_PLAIN], 65 | ["Duration", 5 | Choose2.CHCOL_PLAIN], 66 | ["Activity", 10 | Choose2.CHCOL_PLAIN], 67 | ], 68 | embedded = embedded) 69 | 70 | self.icon = 47 71 | 72 | # Items for display and corresponding data 73 | # NOTE: Could become desynchronized, so to avoid this 74 | # refresh the view after each change. 75 | self.items = [] 76 | 77 | # Initialize/Refresh the view 78 | self.refreshitems() 79 | 80 | def show(self): 81 | # Attempt to open the view 82 | if self.Show() < 0: return False 83 | 84 | return True 85 | 86 | def refreshitems(self): 87 | self.items = [] 88 | 89 | for (t, d, p) in self.pomidor.pomidors: 90 | self.items.append( [t.strftime("%Y-%m-%d %H:%M"), "%d" % (d/60), p]) 91 | 92 | def OnSelectLine(self, n): 93 | pass 94 | 95 | def OnGetLine(self, n): 96 | return self.items[n] 97 | 98 | def OnGetIcon(self, n): 99 | 100 | if not len(self.items) > 0: 101 | return -1 102 | 103 | pomidor_type = self.items[n][2] 104 | 105 | if pomidor_type == "Pomidor": return 61 # green 106 | elif pomidor_type == "Short break": return 60 # yellow 107 | else: return 59 # red 108 | 109 | def OnClose(self): 110 | pass 111 | 112 | def OnGetSize(self): 113 | return len(self.items) 114 | 115 | def OnRefresh(self, n): 116 | self.refreshitems() 117 | return n 118 | 119 | def OnActivate(self): 120 | self.refreshitems() 121 | 122 | ############################################################################### 123 | # Pomidor timer which contains the timer and embedded history view 124 | class PomidorForm(Form): 125 | 126 | def __init__(self, pomidor): 127 | 128 | self.pomidor = pomidor 129 | 130 | Form.__init__(self, 131 | r"""BUTTON YES* NONE 132 | BUTTON NO NONE 133 | BUTTON CANCEL NONE 134 | IDA Pomidor 135 | {FormChangeCb} 136 | {imgPomidor} 137 | 138 | {strTime} 139 | 140 | """, { 141 | 'imgPomidor' : Form.StringLabel(""), 142 | 'FormChangeCb' : Form.FormChangeCb(self.OnFormChange), 143 | 'cEChooser' : Form.EmbeddedChooserControl(self.pomidor.pomidorView, swidth=50), 144 | 145 | 'strTime' : Form.StringLabel(""), 146 | 147 | 'iButtonPomidor' : Form.ButtonInput(self.OnButtonPomidor, swidth=16), 148 | 'iButtonShortBreak': Form.ButtonInput(self.OnButtonShortBreak, swidth=16), 149 | 'iButtonLongBreak' : Form.ButtonInput(self.OnButtonLongBreak, swidth=16), 150 | }) 151 | 152 | self.Compile() 153 | 154 | def OnButtonPomidor(self, code=0): 155 | self.pomidor.timer_start("Pomidor") 156 | 157 | def OnButtonShortBreak(self, code=0): 158 | self.pomidor.timer_start("Short break") 159 | 160 | def OnButtonLongBreak(self, code=0): 161 | self.pomidor.timer_start("Long break") 162 | 163 | def OnFormChange(self, fid): 164 | 165 | # Form initialization 166 | if fid == -1: 167 | 168 | # Fill the top image 169 | self.SetControlValue(self.imgPomidor, "" % os.path.join(self.pomidor.path, "pomidor.png") ) 170 | 171 | # Set current time, possibly resuming an existing timer 172 | self.setTime(self.pomidor.duration) 173 | 174 | # Form OK pressed 175 | elif fid == -2: 176 | pass 177 | 178 | return 1 179 | 180 | def setTime(self, duration): 181 | 182 | # Convert time offset to the form where we could 183 | # iterate over each digit in a list [H0,M1,M0,S1,S0] 184 | time_str = "0%s" % timedelta(seconds = self.pomidor.duration_stop - duration) 185 | time_str = time_str.replace(':','') 186 | 187 | ctrl_str = "" 188 | 189 | for i, t in enumerate(time_str): 190 | t = int(t) 191 | 192 | if i != 0 and not i % 2: 193 | ctrl_str += "" % os.path.join(self.pomidor.path, "separator.png") 194 | 195 | ctrl_str += "" % os.path.join(self.pomidor.path, "flipper%d%d.png" % (t, 2) ) 196 | 197 | self.SetControlValue( self.strTime, ctrl_str ) 198 | 199 | ############################################################################### 200 | # Plugin manager 201 | class PomidorManager(): 202 | 203 | def __init__(self): 204 | 205 | self.addmenu_item_ctxs = list() 206 | self.path = idaapi.idadir( os.path.join("plugins","idapomidor","images") ) 207 | 208 | self.pomidors = list() 209 | 210 | # Initialize the timer 211 | # NOTE: QTimer is a lot more stable compared to idaapi.register_timer() 212 | # unfortunately this requires PySide installation. 213 | self.timer = QtCore.QTimer() 214 | self.timer.timeout.connect(self.timer_callback) 215 | 216 | self.qapp = QtCore.QCoreApplication.instance() 217 | 218 | self.pomidorForm = None 219 | self.pomidorView = PomidorView(self, embedded=True) 220 | 221 | self.interval = 1000 222 | 223 | self.duration = 0 224 | self.duration_stop = 0 225 | self.duration_settings = {"Pomidor": 25*60, "Short break": 5*60, "Long break": 15*60} 226 | 227 | self.update = 0 228 | 229 | self.t = None 230 | 231 | #-------------------------------------------------------------------------- 232 | # Menu Items 233 | #-------------------------------------------------------------------------- 234 | def add_menu_item_helper(self, menupath, name, hotkey, flags, pyfunc, args): 235 | 236 | # add menu item and report on errors 237 | addmenu_item_ctx = idaapi.add_menu_item(menupath, name, hotkey, flags, pyfunc, args) 238 | if addmenu_item_ctx is None: 239 | return 1 240 | else: 241 | self.addmenu_item_ctxs.append(addmenu_item_ctx) 242 | return 0 243 | 244 | def add_menu_items(self): 245 | 246 | if self.add_menu_item_helper("Help/About program..", "IDA Pomidor", "", 1, self.show_pomidor, None): return 1 247 | 248 | return 0 249 | 250 | def del_menu_items(self): 251 | for addmenu_item_ctx in self.addmenu_item_ctxs: 252 | idaapi.del_menu_item(addmenu_item_ctx) 253 | 254 | # Show Form 255 | def show_pomidor(self): 256 | self.pomidorForm = PomidorForm(self) 257 | ok = self.pomidorForm.Execute() 258 | self.pomidorForm.Free() 259 | self.pomidorForm = None 260 | 261 | def timer_start(self,type): 262 | 263 | # Stop the previous active timer 264 | if self.timer.isActive(): 265 | self.timer.stop() 266 | 267 | # Set timer duration 268 | self.duration = 0 269 | self.duration_stop = self.duration_settings[type] 270 | 271 | # Insert the new task into the chooser and update the view 272 | self.pomidors.insert(0, (datetime.now(), self.duration_stop, type)) 273 | self.pomidorView.refreshitems() 274 | self.pomidorForm.RefreshField(self.pomidorForm.cEChooser) 275 | 276 | # Start the timer 277 | self.timer.start(1000) 278 | 279 | def timer_callback(self): 280 | 281 | if self.duration < self.duration_stop: 282 | self.duration += self.interval / 1000 283 | 284 | # Update the UI timer if it is visible 285 | if self.pomidorForm: 286 | self.pomidorForm.setTime(self.duration) 287 | 288 | else: 289 | print "[idapomidor] Timer expired after %d minutes." % (self.duration/60) 290 | self.timer.stop() 291 | self.qapp.beep() 292 | 293 | ## Open the dialog if it's not already opened 294 | if not self.pomidorForm: 295 | self.show_pomidor() 296 | 297 | ############################################################################### 298 | # Plugin 299 | ############################################################################### 300 | class idapomidor_t(plugin_t): 301 | 302 | flags = idaapi.PLUGIN_UNL 303 | comment = "IDA productivity tool that encourages regular breaks." 304 | help = "IDA productivity tool that encourages regular breaks." 305 | wanted_name = "IDA Pomidor" 306 | wanted_hotkey = "" 307 | 308 | def init(self): 309 | global idapomidor_manager 310 | 311 | # Check if already initialized 312 | if not 'idapomidor_manager' in globals(): 313 | 314 | idapomidor_manager = PomidorManager() 315 | if idapomidor_manager.add_menu_items(): 316 | print "Failed to initialize IDA Pomidor." 317 | idapomidor_manager.del_menu_items() 318 | del idapomidor_manager 319 | return idaapi.PLUGIN_SKIP 320 | else: 321 | print("Initialized IDA Pomidor v%s (c) Peter Kacherginsky " % IDAPOMIDOR_VERSION) 322 | 323 | return idaapi.PLUGIN_KEEP 324 | 325 | def run(self, arg): 326 | global idapomidor_manager 327 | idapomidor_manager.show_pomidor() 328 | 329 | def term(self): 330 | global idapomidor_manager 331 | if idapomidor_manager.timer.isActive(): 332 | idapomidor_manager.timer.stop() 333 | del idapomidor_manager 334 | 335 | 336 | def PLUGIN_ENTRY(): 337 | return idapomidor_t() 338 | 339 | ############################################################################### 340 | # Script / Testing 341 | ############################################################################### 342 | 343 | def idapomidor_main(): 344 | 345 | global idapomidor_manager 346 | 347 | if 'idapomidor_manager' in globals(): 348 | idapomidor_manager.del_menu_items() 349 | del idapomidor_manager 350 | 351 | idapomidor_manager = PomidorManager() 352 | idapomidor_manager.add_menu_items() 353 | idapomidor_manager.show_pomidor() 354 | 355 | if __name__ == '__main__': 356 | #idapomidor_main() 357 | pass 358 | -------------------------------------------------------------------------------- /idapomidor/images/flipper00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper00.png -------------------------------------------------------------------------------- /idapomidor/images/flipper01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper01.png -------------------------------------------------------------------------------- /idapomidor/images/flipper02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper02.png -------------------------------------------------------------------------------- /idapomidor/images/flipper10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper10.png -------------------------------------------------------------------------------- /idapomidor/images/flipper11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper11.png -------------------------------------------------------------------------------- /idapomidor/images/flipper12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper12.png -------------------------------------------------------------------------------- /idapomidor/images/flipper20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper20.png -------------------------------------------------------------------------------- /idapomidor/images/flipper21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper21.png -------------------------------------------------------------------------------- /idapomidor/images/flipper22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper22.png -------------------------------------------------------------------------------- /idapomidor/images/flipper30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper30.png -------------------------------------------------------------------------------- /idapomidor/images/flipper31.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper31.png -------------------------------------------------------------------------------- /idapomidor/images/flipper32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper32.png -------------------------------------------------------------------------------- /idapomidor/images/flipper40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper40.png -------------------------------------------------------------------------------- /idapomidor/images/flipper41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper41.png -------------------------------------------------------------------------------- /idapomidor/images/flipper42.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper42.png -------------------------------------------------------------------------------- /idapomidor/images/flipper50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper50.png -------------------------------------------------------------------------------- /idapomidor/images/flipper51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper51.png -------------------------------------------------------------------------------- /idapomidor/images/flipper52.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper52.png -------------------------------------------------------------------------------- /idapomidor/images/flipper60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper60.png -------------------------------------------------------------------------------- /idapomidor/images/flipper61.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper61.png -------------------------------------------------------------------------------- /idapomidor/images/flipper62.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper62.png -------------------------------------------------------------------------------- /idapomidor/images/flipper70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper70.png -------------------------------------------------------------------------------- /idapomidor/images/flipper71.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper71.png -------------------------------------------------------------------------------- /idapomidor/images/flipper72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper72.png -------------------------------------------------------------------------------- /idapomidor/images/flipper80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper80.png -------------------------------------------------------------------------------- /idapomidor/images/flipper81.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper81.png -------------------------------------------------------------------------------- /idapomidor/images/flipper82.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper82.png -------------------------------------------------------------------------------- /idapomidor/images/flipper90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper90.png -------------------------------------------------------------------------------- /idapomidor/images/flipper91.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper91.png -------------------------------------------------------------------------------- /idapomidor/images/flipper92.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/flipper92.png -------------------------------------------------------------------------------- /idapomidor/images/pomidor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/pomidor.png -------------------------------------------------------------------------------- /idapomidor/images/separator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iphelix/ida-pomidor/1e611292eebe5db68bfeaef2b13ceb3f24cc982e/idapomidor/images/separator.png --------------------------------------------------------------------------------