I’ve started using f.lux some time ago and now I cannot live without it. But there is one disadvantage considering my use case. Whenever I want to see a movie (which is usually at evening when f.lux is making everything reddish) I have to disable it manually. Through context menu. Because hotkey allows you to disable it only for one hour. And my movies usually are longer than that. So what can I do? Fire an IDA, of course.
Where to start? I’ve tried to find string that is shown after pressing these keys (ALT + END): “for an hour” and “f.lux is back”. Strings window found it at address 0x483850 and 0x483860 (f.lux v. 3.10 for Windows). IDA could find only one reference to these addresses in single function sub_458330. Great, lets put breakpoint at the beginning of this function and lets see what happen.
Breakpoint will hit frequently after the program starts. It must be some kind of message processor. Ok, lets put breakpoints on lines referenced to strings (0x4585D6 and 0x4585E2 – see picture on the left) instead of begginig of function. Now we can see that it hits only on hotkeys, but not on menu click. Great.
Looking around this place we could find an interesting value. At address 0x4585B9 there is label pointing to double float:
.rdata:00490240 dbl_490240 dq 3600.0
3600 which is number of seconds in hour. Coincidence? And what is this strange fld instruction? Probably some mov with float argument. Lets find it.
I’m not sure but it looks like this value is placed on the stack as argument to sub_452BD0 function. Lets break on this function and try to modify the value on the stack. I found online float to binary converter here http://babbage.cs.qc.cuny.edu/IEEE-754.old/Decimal.html. I’ve tried to change this to 10 secs, which is 0x4024000000000000 (use double precision). It works, so all we need to do is to patch executable with value corresponding to 3 hour time or so and maybe change strings accordingly, right?
Why not “disable until sunrise”?
Why not just remap ALT + END to call this function? It has no shortcut whatsoever. Lets find this string. It is used at address 0x457DD0 as parameter to AppendMenuA function. But it is here registered, not executed. Maybe we should try different approach: lets find xrefs to sub_452BD0. We should find proper message processor associated with menu this way.
There is five of them. Lets break on four yet unexamined. This way we will detect the one called by menu. As we can see, it is 0x457FCF. But wait, there is similar code next to it.
Only difference is in timeout parameter passed to our function – it is -1 this time. Is it some special value to indicate this “until sunrise” mode? Lets find out. We already have breakpoint in here, so we only have to click this option from menu. And it breaks!
Finally our hack comes to modify this single value at address 0x4585B9 (hotkey handling function). Or I suggest to modify instruction to load value -1 from address 0x4901F8 instead to not affect other places where this value is used (and there is several such places). And maybe changing string “for an hour”.
Oh wait, “until sunrise” is too long to fit in there! What now?
Don’t worry, there are at least two possible solutions. We could use another string here. “Until sunrise” is presented at 0x483888. And if you want string that starts with lower case, you could use “Disable until sunrise” at 0x483724 but skipping the first word.
If you still couldn’t find any useful string, you could always add new one. At the end of .rdata section there is more than 400 bytes unused. You can put your string there. Don’t forget to update virtual size of this section in section header.
Unfortunately f.lux license forbids me to publish modified version. Instead, I would present patching instruction in form that it would be easy to patch with any hex editor.
Format: address: original value -> new value where address is file offset hexadecimal value.
"Until sunrise" patch: 579BB: 40 02 49 00 -> F8 01 49 00 579D7: 60 38 48 00 -> 2C 37 48 00
"3 hour" patch: 8F640: 00 00 00 00 00 20 AC 40 -> 00 00 00 00 00 18 C5 40 82C60: "for an hour" -> "for 3 hours"